/*!
*
* \file    MiraCore.c
*
* \brief    SDK implement file.
*
* C file of the functions declaration about MIRA CMMB Demod SDK
*
* \par    Source files
* - MiraCore.c
*
* \par    Copyright (c) 2008 Maxscend Technologies Inc. All rights reserved
*
* PROPRIETARY RIGHTS of Maxscend Technologies Inc. are involved in
* the subject matter of this material.  All manufacturing, reproduction,
* use, and sales rights pertaining to this subject matter are governed
* by the license agreement.  The recipient of this software implicitly
* accepts the terms of the license.
*
* \version
* Revision of last commit: $Rev: 1003 $
* Author of last commit  : $Author: maxscend\chaohui.jiang $
* Date of last commit    : $Date: 2011-01-05 16:31:57 +0800 (星期三, 05 一月 2011) $
*
*/

#define MIRA_OAL_FUNC_IMP

#include "Mxd0250Private.h"

#include "Mxd0250FrameProcess.h"

#ifdef FIELDTEST_UPDATEREG
extern void FieldTestUpdateReg(MXD_HANDLE m_hMiraDevice);
extern void FieldTestReadReg( MXD_HANDLE m_hMiraDevice, int type );
#endif
#define STATEMACHINE
MXD_UINT8 m_scConfigRegTable[6][4]={{REG_SC_INFO_A, REG_SC0_CONFIG_A, REG_SC0_CONFIG_B,REG_SC0_SC1_THR},
{REG_SC_INFO_A, REG_SC1_CONFIG_A, REG_SC1_CONFIG_B,REG_SC0_SC1_THR},
{REG_SC_INFO_B, REG_SC2_CONFIG_A, REG_SC2_CONFIG_B,REG_SC2_SC3_THR},
{REG_SC_INFO_B, REG_SC3_CONFIG_A, REG_SC3_CONFIG_B,REG_SC2_SC3_THR},
{REG_SC_INFO_C, REG_SC4_CONFIG_A, REG_SC4_CONFIG_B,REG_SC4_SC5_THR},
{REG_SC_INFO_C, REG_SC5_CONFIG_A, REG_SC5_CONFIG_B,REG_SC4_SC5_THR}};
MXD_UINT8 m_scRegTable[6][3]={{REG_SC_01_SEED_NUM, REG_SC0_BGN_SLOT, REG_SC0_NUM},
{REG_SC_01_SEED_NUM, REG_SC1_BGN_SLOT, REG_SC1_NUM},
{REG_SC_23_SEED_NUM, REG_SC2_BGN_SLOT, REG_SC2_NUM},
{REG_SC_23_SEED_NUM, REG_SC3_BGN_SLOT, REG_SC3_NUM},
{REG_SC_45_SEED_NUM, REG_SC4_BGN_SLOT, REG_SC4_NUM},
{REG_SC_45_SEED_NUM, REG_SC5_BGN_SLOT, REG_SC5_NUM}};
MXD_UINT8  m_dataAvailReg[6][2] = {{REG_CH0_DATA_AVAIL_CNT_H, REG_CH0_DATA_AVAIL_CNT_L},{REG_CH1_DATA_AVAIL_CNT_H, REG_CH1_DATA_AVAIL_CNT_L},{REG_CH2_DATA_AVAIL_CNT_H, REG_CH2_DATA_AVAIL_CNT_L},
{REG_CH3_DATA_AVAIL_CNT_H, REG_CH3_DATA_AVAIL_CNT_L},{REG_CH4_DATA_AVAIL_CNT_H, REG_CH4_DATA_AVAIL_CNT_L},{REG_CH5_DATA_AVAIL_CNT_H, REG_CH5_DATA_AVAIL_CNT_L}};
MXD_UINT8  m_dataReg[6] = {REG_CH0_DATA_ADDR, REG_CH1_DATA_ADDR, REG_CH2_DATA_ADDR, REG_CH3_DATA_ADDR, REG_CH4_DATA_ADDR, REG_CH5_DATA_ADDR};

MXD_UINT8 g_nAgcMode = 1; /* 0- BBAGC+RFAGC; 1- BBAGC+Host RFAGC; 2- BBAGC + Software RFAGC */
MXD_INT32 g_AddFoHz = 35;
MXD_UINT32 gFreqVhf0Khz = 220000;
MXD_UINT32 gFreqUhf0Khz = 625000;
MXD_UINT32 g_CurrentFreq=0;
MXD_UINT8 g_GubaoState = 0;
MXD_RETURN_CODE DCC_ProcessGubao( MXD_HANDLE hDevice );
/*!
* \par Description
* This function is used to initialize sdk.
* Notice: this SDK could support more than one demod chip operation at once. a handle will br created by this function and other function must have this handle to do further operation .
*
* \param nDemodChipIndex	[IN] the chip index which host is operating, the first index is 0;
* \param callbacks	[IN] give callback functions;
*
* \return   
*    MXD_HANDLE of new device	- this handle need pass in to other functions.
*    NULL	-	the Device create failed.
*
* \warning    
*/
MXD_HANDLE MXD_EXPORT MXD_OpenDevice( MXD_UINT8 nDemodChipIndex, MXD_CALLBACKs* callbacks )
{
	MIRA_DEVICE_HANDLE* pDevice;
	MXD_RETURN_CODE eRtnCode;
	MXD_UINT8 nChipVersion = 0, i;

	pDevice = (MIRA_DEVICE_HANDLE*) MXD_Malloc( sizeof(MIRA_DEVICE_HANDLE) );
	MXD_Memset( pDevice, 0, sizeof(MIRA_DEVICE_HANDLE) );

	pDevice->nDemodChipIndex = nDemodChipIndex;
	pDevice->tDeviceConfig = *MxdPorting_GetDeviceConfig( nDemodChipIndex );
	pDevice->bStartServiceSearch = FALSE;
	pDevice->bSpurExist = FALSE;
	if( callbacks )
		pDevice->m_fnCallbacks = *callbacks;

	MXD_DebugPrint( "Start MXD_OpenDevice at version:%s\n", MIRA_SDK_VERSION );

	switch(pDevice->tDeviceConfig.eDataPath)
	{
	case MXD_I2C:  //I2C
		break;
	case MXD_SPI:  //SPI 
		pDevice->pDevRxBuffer = (MXD_UINT8 *)MXD_Malloc( SPI_BURST_LEN + 200 );
		pDevice->pDevTxBuffer = (MXD_UINT8 *)MXD_Malloc( SPI_BURST_LEN + 200 );
		eRtnCode = DDS_SetupMxdSpi(pDevice);
		if( MXD_RTN_OK != eRtnCode )
		{
			MXD_DebugPrint( "MXD_OpenDevice::Setup mxd spi fail!\n" );
			MXD_Free( pDevice->pDevRxBuffer );
			MXD_Free( pDevice->pDevTxBuffer );
			MXD_Free( pDevice );
			return NULL;
		}
		MXD_WriteRegFields(pDevice, REG_MP2TS_CTRL, 5, 1, 0x0);
		MXD_WriteRegFields(pDevice, REG_SDIO_I2C_CTRL, 2, 1, pDevice->tDeviceConfig.eIntLevel );
		MXD_WriteRegFields(pDevice, REG_SDIO_I2C_CTRL, 3, 1, pDevice->tDeviceConfig.nIntType );
		break;
	case MXD_TS:  //MP2TS
		//setup MP2TS
		//set TS enable
		MXD_WriteRegFields(pDevice, REG_MP2TS_CTRL, 5, 1, 0x1);
		//set TS bandwidth
		MXD_WriteRegFields(pDevice, REG_MP2TS_CTRL, 4, 1, pDevice->tDeviceConfig.eTsBandWidth);
		//set TS trige edge
		MXD_WriteRegFields(pDevice, REG_MP2TS_CTRL, 2, 1, pDevice->tDeviceConfig.eTsTrigeEdage);
		//set TS para mode
		MXD_WriteRegFields(pDevice, REG_MP2TS_CTRL, 1, 1, pDevice->tDeviceConfig.eTsParaMode );
		//set TS byte mode
		MXD_WriteRegFields(pDevice, REG_MP2TS_CTRL, 0, 1, pDevice->tDeviceConfig.eTsByteMode);
		break;
	default:
		break;
	}

	for( i=0; i<100; i++ )
	{
		MXD_EX_ReadReg( pDevice, 0x3a, &nChipVersion );
		if( nChipVersion != 0x10 )
			break;
	}
	if( nChipVersion != 0x10 )
	{
		MXD_DebugPrint( "Chip verison error, check interface! 0x%x, read times %d\n", nChipVersion, i );
		return 0;
	}


	eRtnCode = DCC_WriteCoeff( pDevice );
	if( MXD_RTN_OK != eRtnCode )
	{
		MXD_DebugPrint( "MXD_OpenDevice::Write coeff error!\n" );
		return pDevice;
	}
	eRtnCode = DCC_InitTuner( pDevice );
	if( MXD_RTN_OK != eRtnCode )
	{
		MXD_DebugPrint( "MXD_OpenDevice::Init tuner fail!\n" );
		return pDevice;
	}

	MXD_WriteRegFields(pDevice, REG_SC0_CONFIG_B, 0, 5, 0x00);
	MXD_WriteRegFields(pDevice, REG_SC0_CONFIG_A, 0, 5, 0x00);
	MXD_WriteRegFields(pDevice, REG_SC1_CONFIG_B, 0, 5, 0x00);
	MXD_WriteRegFields(pDevice, REG_SC1_CONFIG_A, 0, 5, 0x00);
	MXD_WriteRegFields(pDevice, REG_SC2_CONFIG_B, 0, 5, 0x00);
	MXD_WriteRegFields(pDevice, REG_SC2_CONFIG_A, 0, 5, 0x00);
	MXD_WriteRegFields(pDevice, REG_SC3_CONFIG_B, 0, 5, 0x00);
	MXD_WriteRegFields(pDevice, REG_SC3_CONFIG_A, 0, 5, 0x00);
	MXD_WriteRegFields(pDevice, REG_SC4_CONFIG_B, 0, 5, 0x00);
	MXD_WriteRegFields(pDevice, REG_SC4_CONFIG_A, 0, 5, 0x00);
	MXD_EX_WriteReg(pDevice, REG_SC_VALID_CFG, 0x00);

	//MXD_EX_WriteReg(pDevice, REG_HIC1_INT_MASK, 0xff);
	//MXD_EX_WriteReg(pDevice, REG_HIC2_INT_MASK, 0xff);

	//
	pDevice->ActiveService[5].pRawFrameBuffer = MXD_Malloc( 8640*2 ); //for CLCH
	//  pDevice->ActiveService[5].pRawFrameBuffer[1] = MXD_Malloc( 8640*2 ); //for CLCH
	pDevice->ActiveService[5].nFrameBufLen = 8640;
	pDevice->ActiveService[5].nBufferLen = 8640*2;
	pDevice->ActiveService[5].nActiveServiceID = 0xffff;
	pDevice->bCLCHEnable = FALSE;

	pDevice->ActiveService[5].pFrameBufferTail = pDevice->ActiveService[5].pRawFrameBuffer;
	//	pDevice->ActiveService[5].nReadIndex  = 0;
	DMX_Initialize( pDevice );

	STE_RequestChangeState( pDevice, MIRASTATE_IDLE, NULL );

	return pDevice;
}


/*!
* \par Description
* This function is used to close device.
*
* \param hDevice	[IN] the handle of chip device which host is operating;
*
* \return   
*    MXD_RTN_OK	-	the call succeeded
*
* \warning    
*/
MXD_RETURN_CODE MXD_EXPORT MXD_CloseDevice( MXD_HANDLE hDevice )
{
	MXD_UINT8 i;
	MIRA_DEVICE_HANDLE* pDevice = (MIRA_DEVICE_HANDLE*) hDevice;



	for( i=0; i<6; i++ )
	{   
		if (pDevice->ActiveService[i].nActiveServiceID != 0 )//&& pDevice->ActiveService[i].nActiveServiceID !=0xffff)
			MXD_StopService(pDevice, pDevice->ActiveService[i].nActiveServiceID);
		if (pDevice->ActiveService[i].pRawFrameBuffer)
			MXD_Free( pDevice->ActiveService[i].pRawFrameBuffer );
	}

	MXD_EX_WriteReg(pDevice, REG_SC_VALID_CFG, 0x00);
	MXD_EX_WriteTunerReg( pDevice, 0x2, 0x3 ); //modified for tuner standby mode @ 2010/03/19  by liuyang 
	DCC_ResetDevice(pDevice);

	if( ( MXD_SPI == pDevice->tDeviceConfig.eControlPath )||( MXD_SPI == pDevice->tDeviceConfig.eDataPath ) )
	{
		DDS_StopMxdSpi( hDevice );
	}

	DMX_Destory( pDevice );

	if (pDevice->pLastEmergencyMsg)
		MXD_Free( pDevice->pLastEmergencyMsg );
	if (pDevice->pLastEmergencyTrigger)
		MXD_Free( pDevice->pLastEmergencyTrigger );
	if (pDevice->pLastVideoParam)
		MXD_Free( pDevice->pLastVideoParam );
	if (pDevice->pLastVideoFrames)
		MXD_Free( pDevice->pLastVideoFrames );
	if (pDevice->pLastAudioParam)
		MXD_Free( pDevice->pLastAudioParam );
	if (pDevice->pLastAudioFrames)
		MXD_Free( pDevice->pLastAudioFrames );
	if (pDevice->pLastEsgdata)
		MXD_Free( pDevice->pLastEsgdata );
	if (pDevice->pDevRxBuffer)
		MXD_Free( pDevice->pDevRxBuffer );
	if (pDevice->pDevTxBuffer)
		MXD_Free( pDevice->pDevTxBuffer );
	if (pDevice)
		MXD_Free( pDevice );
	return MXD_RTN_OK;
}

/*!
* \par Description
* This function is used to start a service channel search progress. this function will return immeditely and the service channel information will come back to the callback functions.
*
* \param hDevice	[IN] the handle of chip device which host is operating;
* \param userParam	[IN]	this parameter will give back to host when SDK call in the callback functions.
* \param nBeginFreqKhz	[IN] the begin freqency to tune, unit is khz
* \param nEndFreqKhz	[IN] the end freqency to tune, unit is khz
* \param nStepFreqKhz	[IN] the step of two freqency to tune, unit is khz
*
* \return   
*    MXD_RTN_OK	-	the call succeeded
*
* \warning      
*/
MXD_RETURN_CODE MXD_EXPORT MXD_StartServiceSearch( MXD_HANDLE hDevice, void* userParam, MXD_UINT32 nBeginFreqKhz, MXD_UINT32 nEndFreqKhz, MXD_UINT32 nStepFreqKhz, MXD_BOOL bGetServiceName )
{
	MIRA_DEVICE_HANDLE* pDevice = (MIRA_DEVICE_HANDLE*) hDevice;
#ifdef STATEMACHINE	
	if( pDevice->eCurrentState >= MIRASTATE_BEGINSEARCH && pDevice->eCurrentState < MIRASTATE_SEARCHDONE )
		return MXD_GENERAL_ERROR;
#endif
	pDevice->bStartServiceSearch = TRUE;
	pDevice->bSystemLockStatus = FALSE;
	pDevice->bStartRecovery = FALSE;
	pDevice->ServiceSearchParam.eSearchStatus = MXD_GENERAL_ERROR;
	pDevice->ServiceSearchParam.nBeginFreqKhz = nBeginFreqKhz;
	pDevice->ServiceSearchParam.nCurrentFreqKhz = nBeginFreqKhz;
	pDevice->ServiceSearchParam.nEndFreqKhz = nEndFreqKhz;
	pDevice->ServiceSearchParam.nStepFreqKhz = nStepFreqKhz;
	pDevice->ServiceSearchParam.pSearchUserParam = userParam;
	pDevice->ServiceSearchParam.bGetServiceName = bGetServiceName;

	if (pDevice->ActiveService[5].pRawFrameBuffer)
		MXD_Free( pDevice->ActiveService[5].pRawFrameBuffer );
	//   MXD_Free( pDevice->ActiveService[5].pRawFrameBuffer[1] );
	pDevice->ActiveService[5].pRawFrameBuffer = MXD_Malloc( 8640*2 ); //for CLCH
	//	pDevice->ActiveService[5].pRawFrameBuffer[1] = MXD_Malloc( 8640*2 ); //for CLCH
	pDevice->ActiveService[5].nFrameBufLen = 8640;
	pDevice->ActiveService[5].nBufferLen = 8640*2;
	pDevice->ActiveService[5].nActiveServiceID = 0xffff;

	pDevice->ActiveService[5].pFrameBufferTail = pDevice->ActiveService[5].pRawFrameBuffer;
	//	pDevice->ActiveService[5].nReadIndex  = 0;

	STE_RequestChangeState( hDevice, MIRASTATE_BEGINSEARCH, NULL );
	return MXD_RTN_OK;
}

/*!
* \par Description
* This function is used to stop current service search progress.
*
* \param hDevice	[IN] the handle of chip device which host is operating;
*
* \return   
*    MXD_RTN_OK	-	the call succeeded
*
* \warning    
*/
MXD_RETURN_CODE MXD_EXPORT MXD_StopServiceSearch( MXD_HANDLE hDevice )
{
	MIRA_DEVICE_HANDLE* pDevice = (MIRA_DEVICE_HANDLE*) hDevice;
	pDevice->bStartServiceSearch = FALSE;
	return MXD_RTN_OK;
}

/*!
* \par Description
* This function is used to lock signal at given freq. this function will return after signal is locked or timeout.
*
* \param hDevice	[IN] the handle of chip device which host is operating;
* \param nFreqKhz	[IN] the freqency to tune, unit is khz
* \param nTimeOut	[IN] the preset time for try to lock the siganl, unit is ms
*
* \return   
*    MXD_RTN_OK	-	the call succeeded
*
* \warning      
*/
MXD_RETURN_CODE MXD_EXPORT MXD_LockFrequency( MXD_HANDLE hDevice, MXD_UINT32 nFreqKhz, MXD_UINT32 nTimeOut )
{
	//todo: check the register if current frequency lock is successed.
	MIRA_DEVICE_HANDLE* pDevice = (MIRA_DEVICE_HANDLE*) hDevice;
	MXD_RETURN_CODE eRtnCode = MXD_GENERAL_ERROR;	
	MXD_UINT32 nStartTime = 0;

	pDevice->eCurrentState = MIRASTATE_IDLE;
	pDevice->ServiceSearchParam.eSearchStatus = MXD_POLLING_STATUS;
	pDevice->ServiceSearchParam.nStcNum = 0;
	pDevice->ServiceSearchParam.bStcStatus = FALSE;
	pDevice->ServiceSearchParam.nBeginFreqKhz = nFreqKhz;
	pDevice->ServiceSearchParam.nCurrentFreqKhz = nFreqKhz;
	pDevice->ServiceSearchParam.nEndFreqKhz = nFreqKhz;

	pDevice->nReSyncNum = 0;
	MXD_EX_WriteReg( pDevice, REG_STC_MISC_CTRL,0x0 );//disable notch filter;
	DCC_ResetDevice( pDevice );

	MXD_DebugPrint( "MXD_LockFrequency::Begin to search ________%d_______ KHz!\n",nFreqKhz );
	eRtnCode = DCC_TuneFrequency( pDevice,nFreqKhz );
	if( MXD_RTN_OK != eRtnCode )
	{
		MXD_DebugPrint( "MXD_LockFrequency::Tune Freq error!\n" );
		pDevice->bStartServiceSearch = FALSE;
		return eRtnCode;
	}	

	if( MXD_RTN_OK != DCC_SyncSignal( pDevice ))
	{
		pDevice->bSystemLockStatus = FALSE;
		return MXD_GENERAL_ERROR;         
	}
	nStartTime = DCC_GetTickCount( hDevice );
	MXD_DebugPrint( "______________start time is %d\n", nStartTime );
	while( DCC_GetTickCount( hDevice ) < (nStartTime + nTimeOut) )
	{
		eRtnCode = DCC_IsSignalLocked( pDevice );
		switch( eRtnCode )
		{
		case MXD_RTN_OK:
			pDevice->bSystemLockStatus = TRUE;
			return MXD_RTN_OK;
			break;
		case MXD_POLLING_STATUS:
			//do nothing, remain current state.
			break;
		case MXD_CLCHCRC_FAIL:

			MXD_DebugPrint("MXD_LockFrequency::Crc fail,Resync...!\n");
			DCC_DetectCheMode( hDevice );

			DCC_DetectFo( hDevice );

			DCC_ResetDevice( hDevice );

			MXD_WriteRegFields( hDevice, REG_CTRL, 7, 1, 1 );
			MXD_EX_WriteReg( hDevice, 0xcf, (MXD_UINT8)(pDevice->foVal));
			MXD_EX_WriteReg( hDevice, 0xd0, (MXD_UINT8)(pDevice->foVal>>8));
			MXD_EX_WriteReg( hDevice, 0xd1, (MXD_UINT8)(pDevice->foVal>>16));

			MXD_EX_WriteReg( hDevice, REG_INIT, 0x1 ); 
			MXD_DebugPrint("MXD_LockFrequency::Cts init!\n");
			pDevice->ServiceSearchParam.nRefTick = 0;                  

			break;
		case MXD_CTS_FAIL:
		case MXD_FTS_FAIL_INT:
		case MXD_TIME_OUT:
		case MXD_FTS_FAIL_CURRENT:
			pDevice->bSystemLockStatus = FALSE;
			return eRtnCode; 
			break;

		default:
			break;	      	
		}
	}
	return eRtnCode;	
}

/*!
* \par Description
* This function is used to search service channel list from locked freq. this function will return until the service channel information come back or timeout accou.
*
* \param hDevice	[IN] the handle of chip device which host is operating;
* \param pinfo	[OUT] the service channel detail in locked frequency;
* \param service_count	[OUT] the service channel count in locked frequency;
* \param nTimeOut	[IN] the preset time for try to lock the siganl, unit is ms
*
* \return   
*    MXD_RTN_OK	-	the call succeeded
*
* \warning      
*/
MXD_RETURN_CODE MXD_EXPORT MXD_RecieveServiceList( MXD_HANDLE hDevice, MXD_CMMBSERVICE_INFO **ppinfo, MXD_UINT32 *pservice_count, MXD_UINT32 nTimeOut, MXD_BOOL bGetServiceName )
{
	MIRA_DEVICE_HANDLE* pDevice = (MIRA_DEVICE_HANDLE*) hDevice;
	MXD_RETURN_CODE eRtnCode = MXD_GENERAL_ERROR;
	MXD_UINT32 nStartTime = DCC_GetTickCount( hDevice );
	MXD_UINT8 uIndex;

	if ( MXD_TS == pDevice->tDeviceConfig.eDataPath && pDevice->m_fnCallbacks.OnReadTsData )
	{
		pDevice->eCurrentState = MIRASTATE_GETCLCH;
		pDevice->eRequestState = MIRASTATE_NULL;
		pDevice->ServiceSearchParam.bGetServiceName = bGetServiceName;
		pDevice->ServiceSearchParam.nCurrentFreqKhz = pDevice->ServiceSearchParam.nEndFreqKhz;
		while( pDevice->eCurrentState != MIRASTATE_SEARCHDONE && DCC_GetTickCount( hDevice ) < nStartTime + nTimeOut )
		{
			MXD_UINT32 nTsDataLen = 0;
			MXD_UINT8* pTsData = NULL;
			pDevice->m_fnCallbacks.OnReadTsData( pDevice->nDemodChipIndex, &pTsData, &nTsDataLen );
			if( nTsDataLen && pTsData )
				MXD_TSPacketProcess( hDevice, pTsData, nTsDataLen );
			if( pDevice->eRequestState == MIRASTATE_STARTESG )
			{
				pDevice->eRequestState = MIRASTATE_NULL;
				pDevice->eCurrentState = MIRASTATE_ESGRECEIVING;
				if( DTP_StartServiceNameReceive( hDevice ) != MXD_RTN_OK )
					pDevice->eCurrentState = MIRASTATE_SEARCHDONE;
			}
			if( pDevice->eRequestState == MIRASTATE_SEARCHDONE )
			{
				if( bGetServiceName )
					DTP_StopServiceNameReceive( hDevice );
				pDevice->eCurrentState = MIRASTATE_SEARCHDONE;
				break;
			}
		}
		if( pDevice->eCurrentState != MIRASTATE_SEARCHDONE )
		{
			return MXD_GENERAL_ERROR;
		}
		else
		{
			MXD_DEMUXER_CONTEXT* pDemuxCtx = (MXD_DEMUXER_CONTEXT*)pDevice->pDemuxerPrivateStruct;
			*ppinfo = pDemuxCtx->m_pSeviceChannelList;
			*pservice_count = pDemuxCtx->m_nServiceCount;
			return MXD_RTN_OK;
		}
	}
	else
	{
		while( eRtnCode != MXD_RTN_OK && DCC_GetTickCount( hDevice ) < nStartTime + nTimeOut )
			eRtnCode = DTP_ClchProcess(pDevice,ppinfo,pservice_count);

		if( eRtnCode == MXD_RTN_OK && bGetServiceName )
		{
			eRtnCode = MXD_GENERAL_ERROR;
			if( DTP_StartServiceNameReceive( hDevice ) != MXD_RTN_OK )
			{
				pDevice->eCurrentState = MIRASTATE_SEARCHDONE;
				eRtnCode = MXD_RTN_OK;
			}
			else
			{
				while( DCC_GetTickCount( hDevice ) < nStartTime + nTimeOut )
				{
					DTP_CheckServiceData(pDevice, &uIndex);
					if (uIndex)
					{
						eRtnCode = DTP_ServiceDataProcess(pDevice, uIndex, TRUE);
						if( MXD_RTN_OK == eRtnCode )
						{
							MXD_DEMUXER_CONTEXT* pDemuxCtx = (MXD_DEMUXER_CONTEXT*)pDevice->pDemuxerPrivateStruct;
							*ppinfo = pDemuxCtx->m_pSeviceChannelList;
							*pservice_count = pDemuxCtx->m_nServiceCount;
							break;
						}
					}
				}
				DTP_StopServiceNameReceive( hDevice );
				eRtnCode = MXD_RTN_OK;
			}
		}
		if( eRtnCode != MXD_RTN_OK )
			return MXD_GENERAL_ERROR;
	}

	return eRtnCode;
}

/*!
* \par Description
* This function is used to set tuner frequency after lock the signal.
*
* \param pSavedSeviceChannelList	[ IN ]	saved service channel list.
* \param service_count	[ IN ]	service count in the service channel list.
*
* \return   
*    MXD_RTN_OK	-	the call succeeded
*
* \warning      
*/
MXD_RETURN_CODE MXD_EXPORT MXD_RestoreServiceList( MXD_HANDLE hDevice, MXD_CMMBSERVICE_INFO *pSavedSeviceChannelList, MXD_UINT32 service_count )
{
	MIRA_DEVICE_HANDLE* pDevice = (MIRA_DEVICE_HANDLE*) hDevice;
	DMX_SetServiceInfoList( hDevice, pSavedSeviceChannelList, service_count );
	pDevice->eCurrentState = MIRASTATE_NULL;
	return MXD_RTN_OK;
}

MXD_RETURN_CODE DTP_FindMemForService( MXD_HANDLE hDevice, MXD_UINT8 nMemReq, MXD_UINT8* pMemStart )
{
	MXD_UINT8 nMemInd[24], i, nStartBlk, nBlockNum, j;
	MXD_Memset( &nMemInd, 0, sizeof(nMemInd) );

	if( nMemReq>24 )
		return MXD_GENERAL_ERROR;

	for( i=0; i<6; i++ )
	{
		MXD_ReadRegFields(hDevice, m_scConfigRegTable[i][2], 0, 5, &nStartBlk);
		MXD_ReadRegFields(hDevice, m_scConfigRegTable[i][1], 0, 5, &nBlockNum);

		for( j=nStartBlk; j<nStartBlk+nBlockNum; j++ )
			nMemInd[j] = 1;
	}

	for( i=0; i<24; i++ )
	{
		if( nMemInd[i] == 0 )
		{
			for( j=i; j<i+nMemReq && j<24; j++ )
				if( nMemInd[j] == 1 )
					break;
			if( j == i+nMemReq )
			{
				*pMemStart = i;
				return MXD_RTN_OK;
			}
		}
	}
	return MXD_GENERAL_ERROR;
}

/*!
* \par Description
* This function is used to config a service channel.
*
* \param hDevice	[IN] the handle of chip device which host is operating;
* \param serviceID	[IN]	the index of the channel service.
* \
*
* \return   
*    MXD_RTN_OK	-	the call succeeded
*
* \warning      
*/
MXD_RETURN_CODE DTP_ConfigService(MXD_HANDLE hDevice, MXD_UINT32 serviceID, MXD_UINT8 Index)
{
	MXD_UINT8  i,j              = 0;
	MXD_UINT32 m_uBuffLenth     = 0;
	MXD_UINT8  m_qamType        = 0;
	MXD_UINT8  m_inerleaveMode  = 0;
	MXD_UINT8  m_rsmode         = 0;
	MXD_UINT8  m_DeblocNum      = 0;
	MXD_UINT8  m_preStartBlk    = 0;
	MXD_UINT8  m_nextStartBlk   = 0;
	MXD_UINT8  m_preBlockNum    = 0;
	MXD_UINT8  m_nextBlockNum   = 0;
	MXD_UINT8  m_cuurStartBlk   = 0;
	MXD_UINT8  m_schDataThr     = 0;    
	MXD_UINT32 m_DeinterThr     = 0;
	MXD_UINT8* m_regTable = 0;
	MIRA_DEVICE_HANDLE*   pDevice = NULL;
	MXD_CMMBSERVICE_INFO* pCmmbServiceInfo = NULL;

	if (hDevice == NULL)
	{
		return MXD_GENERAL_ERROR;
	}
	pDevice = (MIRA_DEVICE_HANDLE*) hDevice;
	//Get service info handle  
	pCmmbServiceInfo = ((MXD_DEMUXER_CONTEXT*)pDevice->pDemuxerPrivateStruct)->m_pSeviceChannelList;
	for( i = 0;i < ((MXD_DEMUXER_CONTEXT*)pDevice->pDemuxerPrivateStruct)->m_nServiceCount; i++)
	{
		if (serviceID == pCmmbServiceInfo->nServiceID )
		{
			break;
		}
		pCmmbServiceInfo++;
	}
	if( ! pCmmbServiceInfo )
		return MXD_GENERAL_ERROR;
	//set qam type
	m_regTable = m_scConfigRegTable[Index];
	switch(pCmmbServiceInfo->eModuType)
	{
	case MXD_MODULATE_TYPE_BPSK:  //BPSK
		if (Index%2==0)
		{
			MXD_WriteRegFields(pDevice, *m_regTable, 0, 2, 0x00);
		}
		else
		{
			MXD_WriteRegFields(pDevice, *m_regTable, 3 , 2, 0x00);
		}
		m_qamType = 1;
		break;
	case MXD_MODULATE_TYPE_QPSK:  //QPSK
		if (Index%2==0)
		{
			MXD_WriteRegFields(pDevice, *m_regTable, 0, 2, 0x01);
		}
		else
		{
			MXD_WriteRegFields(pDevice, *m_regTable, 3, 2, 0x01);
		}
		//	MXD_EX_WriteReg( hDevice, autoscale_refbitwidth_fw_h, 0x13 );
		//	MXD_EX_WriteReg( hDevice, autoscale_refbitwidth_fw_l, 0x17 );	
		m_qamType = 2;
		break;
	case MXD_MODULATE_TYPE_16QAM: //16QAM
		if (Index%2==0)
		{
			MXD_WriteRegFields(pDevice, *m_regTable, 0, 2, 0x02);
		}
		else
		{
			MXD_WriteRegFields(pDevice, *m_regTable, 3, 2, 0x02);
		}
		//	MXD_EX_WriteReg( hDevice, autoscale_refbitwidth_fw_h, 0x14 );
		//  MXD_EX_WriteReg( hDevice, autoscale_refbitwidth_fw_l, 0x1f );
		m_qamType = 4;
		break;
	default:
		MXD_DebugPrint("MXD_PlayService:illegal QamType!\n");
		return MXD_GENERAL_ERROR;
	}
	//set LDPC
	switch(pCmmbServiceInfo->eLdpcMode)
	{
	case 0:
		if (Index%2==0)
		{
			MXD_WriteRegFields(pDevice, *m_regTable, 2, 1, 0x0);
		}
		else
		{
			MXD_WriteRegFields(pDevice, *m_regTable, 5, 1, 0x0);
		}
		break;
	case 1:
		if (Index%2==0)
		{
			MXD_WriteRegFields(pDevice, *m_regTable, 2, 1, 0x1);
		}
		else
		{
			MXD_WriteRegFields(pDevice, *m_regTable, 5, 1, 0x1);
		}
		MXD_EX_WriteReg( hDevice, REG_AUTOSCALE_FWBITWIDTH, 0x02 );//for 3/4
		break;
	default:
		MXD_DebugPrint("MXD_PlayService:illegal LDPC Type!\n");
		return MXD_GENERAL_ERROR;
		break;
	}
	m_regTable++;
	// set de-interleave
	switch(pCmmbServiceInfo->eInterleaveMode)
	{
	case 0:
	case MXD_INTERLEAVE_MODE_MODE_1:
		MXD_WriteRegFields(pDevice, *m_regTable, 5, 2, 0x01);
		m_inerleaveMode = 1;
		break;
	case MXD_INTERLEAVE_MODE_MODE_2:
		MXD_WriteRegFields(pDevice,  *m_regTable, 5, 2, 0x02);
		m_inerleaveMode = 2;
		break;
	case MXD_INTERLEAVE_MODE_MODE_3:			
		MXD_WriteRegFields(pDevice,  *m_regTable, 5, 2, 0x03);
		m_inerleaveMode = 4;
		break;
	default:
		MXD_DebugPrint("MXD_PlayService:illegal Interleave mode!\n");
		return MXD_GENERAL_ERROR;
		//	break;
	}

	m_regTable++;
	//set RS type
	switch(pCmmbServiceInfo->eRsMode)
	{
	case MXD_RS_MODE_240_240:
		MXD_WriteRegFields(pDevice, *m_regTable, 5, 3, 0x00);
		m_rsmode = 240;
		break;
	case MXD_RS_MODE_240_224:
		MXD_WriteRegFields(pDevice, *m_regTable, 5, 3, 0x01);
		m_rsmode = 224;
		break;
	case MXD_RS_MODE_240_192:
		MXD_WriteRegFields(pDevice, *m_regTable, 5, 3, 0x02);
		m_rsmode = 192;
		break;
	case MXD_RS_MODE_240_176:
		MXD_WriteRegFields(pDevice, *m_regTable, 5, 3, 0x03);
		m_rsmode = 176;
		break;
	default:
		MXD_DebugPrint("MXD_PlayService:illegal RS mode!\n");
		return MXD_GENERAL_ERROR;
		//break;
	}
	m_regTable++;
	//set start block	                    
	//set block numbers
	m_DeblocNum = DTP_CaculateBockNum(pDevice, serviceID);
#ifdef DOUBLE_TV_MEM
	if( pCmmbServiceInfo->eServiceType == MXD_CMMBSERVICE_TYPE_TV )
		m_DeblocNum = m_DeblocNum*2;
#endif
	if (!m_DeblocNum)
	{
		MXD_DebugPrint("Calculate incorrect block nums!\n");
	}
	else
	{
		//MXD_DebugPrint("------block nums: %d\n", m_DeblocNum );
	}
	if (MXD_TS == pDevice->tDeviceConfig.eDataPath) //for TS
	{
		MXD_WriteRegFields(pDevice, m_scConfigRegTable[Index][2], 0, 5, 0);
		MXD_WriteRegFields(pDevice, m_scConfigRegTable[Index][1], 0, 5, m_DeblocNum);
	}
	else
	{
		if( MXD_RTN_OK != DTP_FindMemForService( pDevice, m_DeblocNum, &m_cuurStartBlk ) )
		{
			MXD_DebugPrint("MXD_PlayService: service memory bloc is full!\n");
			return MXD_GENERAL_ERROR;
		}
		else
		{
			MXD_WriteRegFields(pDevice, m_scConfigRegTable[Index][2], 0, 5, m_cuurStartBlk);
			MXD_WriteRegFields(pDevice, m_scConfigRegTable[Index][1], 0, 5, m_DeblocNum);
		}
	}
	//
	//calculate service channel data frame size
	m_DeinterThr = pCmmbServiceInfo->eLdpcMode==0 ? (138240*m_qamType)*1/(8*2*240)*m_rsmode
		:(138240*m_qamType)*3/(8*4*240)*m_rsmode;
	m_schDataThr = (pCmmbServiceInfo->nTsCount * m_qamType)/(2*m_inerleaveMode);
	pDevice->ActiveService[Index].nActiveServiceID    = serviceID;
	pDevice->ActiveService[Index].nFrameBufLen        = pCmmbServiceInfo->nTsCount * m_DeinterThr;
	//
	if ( (pCmmbServiceInfo->nTsCount * m_qamType)%(2*m_inerleaveMode) == 0)
	{
		if (m_schDataThr > 0)
		{
			m_uBuffLenth = pDevice->ActiveService[Index].nFrameBufLen;
		}
	}
	else
	{
		if (m_schDataThr > 0)
		{
			m_uBuffLenth = (m_schDataThr + 1) * m_DeinterThr*((2*m_inerleaveMode)/m_qamType);
		}
		else
		{
			m_uBuffLenth   = m_DeinterThr * ((2*m_inerleaveMode)/m_qamType);
			m_schDataThr += 1;
		}
		pDevice->ActiveService[Index].nFrameBufLen = m_uBuffLenth;
	}
	//
	pDevice->ActiveService[Index].pRawFrameBuffer  = MXD_Malloc( m_uBuffLenth ); //todo: malloc fit block by service type.
	pDevice->ActiveService[Index].nBufferLen          = m_uBuffLenth;
	pDevice->ActiveService[Index].pFrameBufferTail    = pDevice->ActiveService[Index].pRawFrameBuffer;
	pDevice->ActiveService[Index].bCorrectDataGot = FALSE;
	if (Index%2 == 0)
		MXD_WriteRegFields(pDevice, *m_regTable, 4, 4, m_schDataThr);
	else
		MXD_WriteRegFields(pDevice, *m_regTable, 0, 4, m_schDataThr);

	return MXD_RTN_OK;
}

/*!
* \par Description
* This function is used to trige starting a service channel.
*
* \param hDevice	[IN]    the handle of chip device which host is operating;
* \param serviceID	[IN]	the ID of the channel service.
* \param userParam	[IN]	this parameter will give back to host when SDK call in the callback functions.
*
* \return   
*    MXD_RTN_OK	-	the call succeeded
*
* \warning      
*/
MXD_RETURN_CODE DTP_TrigeServiceReceive(MXD_HANDLE hDevice, MXD_UINT32 serviceID, MXD_UINT8 Index)
{
	MXD_UINT8 i = 0;//j = 0;
	MXD_CMMBSERVICE_INFO* pCmmbServiceInfo = NULL;
	MIRA_DEVICE_HANDLE*   pDevice = NULL;
	MXD_UINT8* m_regTable = NULL;
	if (hDevice == NULL)
	{
		return MXD_GENERAL_ERROR;
	}
	pDevice = (MIRA_DEVICE_HANDLE*) hDevice;
	//Get service info handle  
	pCmmbServiceInfo = ((MXD_DEMUXER_CONTEXT*)pDevice->pDemuxerPrivateStruct)->m_pSeviceChannelList;
	for( i = 0; i < ((MXD_DEMUXER_CONTEXT*)pDevice->pDemuxerPrivateStruct)->m_nServiceCount;  i++)
	{
		if (serviceID == pCmmbServiceInfo->nServiceID )
		{
			break;
		}
		pCmmbServiceInfo++;
	}
	m_regTable = m_scRegTable[Index];
	//clear interrupt
	MXD_WriteRegFields(pDevice, REG_HIC1_INT_CLEAR, Index, 1, 0x1);
	MXD_WriteRegFields(pDevice, REG_OTDD_INT_CLEAR, Index, 1, 0x1);
	//set data interrupt thr;
	//set scramble number
	if (Index%2==0)
		MXD_WriteRegFields(pDevice, *m_regTable, 0, 3, pCmmbServiceInfo->nDisturbMode);
	else
		MXD_WriteRegFields(pDevice, *m_regTable, 3, 3, pCmmbServiceInfo->nDisturbMode);
	m_regTable++;
	//set sc0 begin slot
	MXD_WriteRegFields(pDevice, *m_regTable, 0, 5, pCmmbServiceInfo->nStartTs);
	m_regTable++;
	//set sc0 slot number
	MXD_WriteRegFields(pDevice, *m_regTable , 0, 5, pCmmbServiceInfo->nTsCount);
	//set tracking mode
	MXD_WriteRegFields(	hDevice, REG_SFO_TRACK_CFG, 0, 5 ,pCmmbServiceInfo->nStartTs);
	//set sc valid
	MXD_WriteRegFields(pDevice, REG_SC_VALID_CFG, Index, 1, 0x1);
	return MXD_RTN_OK;
}
/*!
* \par Description
* This function is used to start a service channel. the service data will come back to the callback functions.
*
* \param hDevice	[IN] the handle of chip device which host is operating;
* \param serviceID	[IN]	the ID of the channel service.
* \param userParam	[IN]	this parameter will give back to host when SDK call in the callback functions.
*
* \return   
*    MXD_RTN_OK	-	the call succeeded
*
* \warning      
*/
MXD_RETURN_CODE MXD_EXPORT MXD_PlayService( MXD_HANDLE hDevice, MXD_UINT32 serviceID, void* userParam )
{
	MXD_INT32  i = 0, nRealChIndex = 0;
	MXD_RETURN_CODE eRtnCode = MXD_RTN_OK;
	MIRA_DEVICE_HANDLE* pDevice = NULL;
	MXD_UINT8 regVal = 0;
	static MXD_INT8 nRealChStartIndex=0;

	if (hDevice == NULL)
	{
		return MXD_GENERAL_ERROR;
	}
	pDevice = (MIRA_DEVICE_HANDLE*) hDevice;

	pDevice->bStartServicePlay = TRUE;
	//Get service info handle  
	MXD_WriteRegFields( hDevice, REG_SFO_TRACK_CFG, 0x06, 2, 1); // 1s track mode
	MXD_WriteRegFields( hDevice, REG_CTRL, 0x6,1, 0x0); // set ts slice mode

	for( i=0; i<6; i++ )
	{
		if (pDevice->ActiveService[i].nActiveServiceID == serviceID )
		{
			MXD_DebugPrint("This service already open!\n");
			return MXD_RTN_OK;
		}
	}

	for( i=0; i<6; i++ )
	{
		//to aviod waiting at switch channle, we need use next channle index when switch to new service.
		nRealChIndex = nRealChStartIndex + i;
		if( i==5 )
			nRealChIndex = 5; //the last channle reserved for clch, make it as last one.
		else if( nRealChIndex>=5 )
			nRealChIndex = nRealChIndex - 5;

		if( pDevice->ActiveService[nRealChIndex].nActiveServiceID == 0 )
		{
			DMX_RegisterServiceUserParam( hDevice, serviceID, userParam );

			//close clch to save power
			MXD_EX_ReadReg(pDevice, REG_SC_VALID_CFG, &regVal);
			if ((regVal & 0x20)&&(pDevice->bCLCHEnable == FALSE))
			{
				MXD_WriteRegFields(pDevice, REG_SC_VALID_CFG,   5, 1, 0x0);
				MXD_WriteRegFields(pDevice, REG_OTDD_INT_CLEAR, 5, 1, 0x1);
				MXD_WriteRegFields(pDevice, REG_HIC1_INT_CLEAR, 5, 1, 0x1);
				MXD_WriteRegFields(pDevice, REG_SC5_CONFIG_B,   0, 5, 0x00);
				MXD_WriteRegFields(pDevice, REG_SC5_CONFIG_A,   0, 5, 0x00);
				pDevice->ActiveService[5].nActiveServiceID = 0x0;
			}

			eRtnCode = DTP_ConfigService(pDevice, serviceID, nRealChIndex);
			if (MXD_RTN_OK != eRtnCode)
			{
				continue;
			}
			eRtnCode = DTP_TrigeServiceReceive(pDevice, serviceID, nRealChIndex);
			if (MXD_RTN_OK != eRtnCode)
			{
				MXD_DebugPrint( "MXD_PlayService: trige service recieve err!\n" );
			}

			nRealChStartIndex = nRealChStartIndex<4 ? (nRealChStartIndex+1) : 0;
			break;
		}
	}

	if( i == 6 )
	{
		MXD_DebugPrint( "Maximal 6 service support!\n" );
		return MXD_GENERAL_ERROR;
	}

	DTP_SetLDPCRSWindow(pDevice);
	STE_RequestChangeState( hDevice, MIRASTATE_DATARECEIVING, NULL );
	return MXD_RTN_OK;
}

/*!
* \par Description
* This function is used to always open CLCH channel. the service data will come back to the callback functions.
*
* \param hDevice	[IN] the handle of chip device which host is operating;
* \param userParam	[IN]	this parameter will give back to host when SDK call in the callback functions.
*
* \return   
*    MXD_RTN_OK	-	the call succeeded
*
* \warning      
*/
MXD_RETURN_CODE MXD_EXPORT MXD_OpenCLCHService( MXD_HANDLE hDevice, void* userParam )
{
	MXD_RETURN_CODE eRtnCode = MXD_RTN_OK;
	MIRA_DEVICE_HANDLE* pDevice = (MIRA_DEVICE_HANDLE*)hDevice;
	MXD_UINT8 regVal = 0;

	if (pDevice == NULL)
	{
		return MXD_GENERAL_ERROR;
	}

	MXD_EX_ReadReg(pDevice, REG_SC_VALID_CFG, &regVal);
	if (pDevice->bCLCHEnable == FALSE)
	{
		pDevice->bCLCHEnable = TRUE;
		MXD_EX_WriteReg(pDevice, m_scConfigRegTable[5][1], 0x01 );
		MXD_EX_WriteReg(pDevice, m_scConfigRegTable[5][2], 0x16 );
		MXD_WriteRegFields(pDevice, REG_SC_VALID_CFG,   5, 1, 1);
		pDevice->ActiveService[5].nActiveServiceID = 0xffff;
	}
	return eRtnCode;
}

/*!
* \par Description
* This function is used to stop CLCH service.
*
* \param hDevice   [IN] the handle of chip device which host is operating;
* \param userParam [IN]    this parameter will give back to host when SDK call in the callback functions.
*
* \return
*    MXD_RTN_OK    -   the call succeeded
*
* \warning
*/
MXD_RETURN_CODE MXD_EXPORT MXD_StopCLCHService(MXD_HANDLE hDevice)
{
	MXD_RETURN_CODE eRtnCode = MXD_RTN_OK;
	MIRA_DEVICE_HANDLE* pDevice = NULL;

	if (hDevice == NULL)
	{
		return MXD_GENERAL_ERROR;
	}

	pDevice = (MIRA_DEVICE_HANDLE*) hDevice;
	pDevice->bCLCHEnable = FALSE;
	/*  MXD_WriteRegFields(pDevice, REG_SC_VALID_CFG,   5, 1, 0x0);
	MXD_WriteRegFields(pDevice, REG_OTDD_INT_CLEAR, 5, 1, 0x1);
	MXD_WriteRegFields(pDevice, REG_HIC1_INT_CLEAR, 5, 1, 0x1);
	MXD_WriteRegFields(pDevice, REG_SC5_CONFIG_B,   0, 5, 0x00);
	MXD_WriteRegFields(pDevice, REG_SC5_CONFIG_A,   0, 5, 0x00);
	pDevice->ActiveService[5].nActiveServiceID = 0x0;*/
	return eRtnCode;
}
/*!
* \par Description
* This function is used to stop a service channel.
*
* \param hDevice	[IN] the handle of chip device which host is operating;
* \param serviceID	[IN]	the ID of the channel service.
*
* \return   
*    MXD_RTN_OK	-	the call succeeded
*
* \warning    
*/
MXD_RETURN_CODE MXD_EXPORT MXD_StopService( MXD_HANDLE hDevice, MXD_UINT32 serviceID )
{
	MIRA_DEVICE_HANDLE* pDevice = (MIRA_DEVICE_HANDLE*) hDevice;
	MXD_INT32 i = 0;
	MXD_UINT8* m_regTable = 0;
	pDevice->bStartServicePlay = TRUE;

	for( i=0;  i<6;  i++ )
	{
		if( pDevice->ActiveService[i].nActiveServiceID == serviceID )
		{
			pDevice->ActiveService[i].nActiveServiceID = 0;

			DMX_UnregisterServiceUserParam( pDevice, serviceID );
			//todo: set register to stop service receiving.
			//sc valid disable
			MXD_WriteRegFields(pDevice, REG_SC_VALID_CFG, i,1 ,0x0);
			m_regTable = m_scConfigRegTable[i];
			m_regTable++;
			MXD_WriteRegFields(pDevice, *m_regTable, 0, 5, 0x00);
			m_regTable++;
			MXD_WriteRegFields(pDevice, *m_regTable, 0, 5, 0x00);
			if (i%2 == 0)
				MXD_WriteRegFields(pDevice, *m_regTable, 4, 4, 0x00);
			else
				MXD_WriteRegFields(pDevice, *m_regTable, 0, 4, 0x00);
			m_regTable = m_scRegTable[i];
			if (i%2 == 0)
				MXD_WriteRegFields(pDevice,  *m_regTable, 0 ,3, 0x00);
			else
				MXD_WriteRegFields(pDevice,  *m_regTable, 3 ,3, 0x00);
			m_regTable++;
			MXD_EX_WriteReg(pDevice, *m_regTable, 0x00);
			m_regTable++;
			MXD_EX_WriteReg(pDevice, *m_regTable, 0x00);
			MXD_WriteRegFields(pDevice, REG_HIC1_INT_CLEAR, i, 1, 0x1);

			if (pDevice->ActiveService[i].pRawFrameBuffer)
			{
				MXD_Free( pDevice->ActiveService[i].pRawFrameBuffer );
			}
			pDevice->ActiveService[i].pRawFrameBuffer = NULL;
			pDevice->ActiveService[i].pFrameBufferTail   = NULL;
			break;
		}
	}
	pDevice->nLastStopTick = DCC_GetTickCount( hDevice );
	if( i == 6 )
	{
		MXD_DebugPrint( "Try to stop service which not existed!\n" );
		return MXD_GENERAL_ERROR;
	}
	DTP_SetLDPCRSWindow(pDevice);
	for( i=0;  i<6;  i++ )
	{
		if( pDevice->ActiveService[i].nActiveServiceID  )
			break;
	}
	if( i == 5 )
	{
		//all service down, return to idel state
		STE_RequestChangeState( hDevice, MIRASTATE_IDLE, NULL );
	}
	return MXD_RTN_OK;
}

/*!
* \par Description
* This function intercept all started service. When service data arrived, it will demux received data and call registed callback functions. Without it all callback functions will not work!
* This function must been called from an High ISR routine or a Timer task. 
* If host call this function in a timer task, the period of two calling must no longer than 100ms.
*
* \param hDevice	[IN] the handle of chip device which host is operating;
*
* \return   
*    MXD_RTN_OK	-	the call succeeded
*
* \warning     
*/
MXD_RETURN_CODE MXD_EXPORT MXD_PulseProcess( MXD_HANDLE hDevice )
{
	MIRA_DEVICE_HANDLE* pDevice = (MIRA_DEVICE_HANDLE*) hDevice;
	MXD_UINT8	 intTimeOut;
	MXD_UINT8  nLNA;
	static MXD_UINT32 nLastTick = 0;

	MXD_EX_ReadReg(pDevice, REG_OTDD_INT_STATUS, &intTimeOut);
	if ( (intTimeOut & REG_TDP_IR_TIMEOUT_INT_STATUS_BIT))
	{
		MXD_DebugPrint("timeout intr:%x  at time: %d\n", intTimeOut, DCC_GetTickCount(hDevice));
		//clear timeout interrupt
		MXD_WriteRegFields(pDevice, REG_OTDD_INT_CLEAR, 6, 1, 0x1);
	}

	//  nLastTick = DCC_GetTickCount(hDevice);
	if ( DCC_GetTickCount(hDevice) - nLastTick >= 250)
	{
#ifdef FIELDTEST_UPDATEREG
		FieldTestReadReg(hDevice,1);
#endif
		nLastTick = DCC_GetTickCount(hDevice);
		// MXD_DebugPrint("Print ticks at time: %d\n", nLastTick);
	}

	MXD_EX_ReadTunerReg(pDevice, 0x77, &nLNA);
	if( nLNA != pDevice->nLastLNA )
	{
		MXD_UINT8  nLNA2;
		MXD_EX_ReadTunerReg(pDevice, 0x77, &nLNA2);
		if( nLNA2 == nLNA )
		{
			MXD_UINT8 nRegTab1[] = {0x28, 0x28, 0x28, 0x28, 0x1c, 0x19};
			MXD_UINT8 nRegTab2[] = {0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x19};
			MXD_UINT8 nRegTab3[] = {0x19, 0x19, 0x19, 0x19, 0x19, 0x19};
			MXD_UINT8 nRegTab4[] = {0x2f, 0x2d, 0x2b, 0x28, 0x1c, 0x19};
			MXD_UINT8 i;
			switch( nLNA )
			{
			case 0x01:
				for( i=0; i<sizeof(nRegTab1); i++ )
					MXD_EX_WriteTunerReg( pDevice, 0xe0+i, nRegTab1[i] );
				break;
			case 0x02:
			case 0x04:
			case 0x05:
				for( i=0; i<sizeof(nRegTab2); i++ )
					MXD_EX_WriteTunerReg( pDevice, 0xe0+i, nRegTab2[i] );
				break;
			case 0x03:
				for( i=0; i<sizeof(nRegTab3); i++ )
					MXD_EX_WriteTunerReg( pDevice, 0xe0+i, nRegTab3[i] );
				break;
			case 0x06:
				for( i=0; i<sizeof(nRegTab4); i++ )
					MXD_EX_WriteTunerReg( pDevice, 0xe0+i, nRegTab4[i] );
				break;
			}
			pDevice->nLastLNA = nLNA;
		}
	}

#ifdef STATEMACHINE
	STE_StateProcess( hDevice );
#else

	if( pDevice->bSystemLockStatus )
	{
		eRtnCode = DCC_GetSystemStatus( pDevice );
		if( MXD_SYSTEM_UNLOCK == eRtnCode )
		{
			pDevice->bSystemLockStatus = FALSE;
			pDevice->bStartServiceSearch = TRUE;
			//			pDevice->ServiceSearchParam.nSearchedFreqKhz = 0;
			pDevice->bStartRecovery = TRUE;
			pDevice->bRecoveryStatus = TRUE;
			pDevice->ServiceSearchParam.eSearchStatus = MXD_GENERAL_ERROR;
			MXD_DebugPrint( "MXD_PulseProcess::System unlock, Begin to Recovery!\n" );
			return MXD_RTN_OK;
		}
		else
		{
			DCC_DetectCheMode( hDevice );
		}
	}
	if( pDevice->bStartServiceSearch )
	{
		//check the register if current frequency lock is successed.
		if( pDevice->ServiceSearchParam.eSearchStatus != MXD_CLCHDATA_OK && pDevice->ServiceSearchParam.eSearchStatus != MXD_CLCHCRC_PASS )
		{ 
			eRtnCode = DCC_SearchFrequency( pDevice );
			if( MXD_RTN_OK != eRtnCode )
			{
				return MXD_RTN_OK;   
			}
		}
		//check  if data path is ts ?
		if ( (MXD_TS != pDevice->tDeviceConfig.eDataPath)&&(!pDevice->bStartRecovery))
		{
			if( pDevice->ServiceSearchParam.eSearchStatus == MXD_CLCHCRC_PASS )
			{
				eRtnCode = DTP_ClchProcess(pDevice,&psvrInfos,&servicecount);
				if (MXD_RTN_OK==eRtnCode)
				{
					// when service name function actived, search work will not stop until the service name received from esg.
					if( pDevice->ServiceSearchParam.bGetServiceName )
					{
						if( MXD_RTN_OK == DTP_StartServiceNameReceive( hDevice ) )
						{
							pDevice->ServiceSearchParam.eSearchStatus = MXD_CLCHDATA_OK;
							pDevice->ServiceSearchParam.nRefTick = DCC_GetTickCount( hDevice );
						}
					}
					if( pDevice->ServiceSearchParam.eSearchStatus == MXD_CLCHCRC_PASS )
					{
						if( pDevice->m_fnCallbacks.OnServiceSearchResult )
							pDevice->m_fnCallbacks.OnServiceSearchResult( pDevice->nDemodChipIndex, pDevice->ServiceSearchParam.pSearchUserParam, pDevice->ServiceSearchParam.nCurrentFreqKhz, psvrInfos, servicecount );

						//change to next frequency.
						pDevice->ServiceSearchParam.eSearchStatus = MXD_RTN_OK;

						//stop search progress if all frequency scaned.
						if( pDevice->ServiceSearchParam.nCurrentFreqKhz >= pDevice->ServiceSearchParam.nEndFreqKhz )
						{
							MXD_DebugPrint( "Batch frequency search (from %d to %d) finished!\n", pDevice->ServiceSearchParam.nBeginFreqKhz, pDevice->ServiceSearchParam.nEndFreqKhz );
							pDevice->bStartServiceSearch = FALSE;
						}
					}
				}
				else if( MXD_GENERAL_ERROR == eRtnCode )
				{
					pDevice->ServiceSearchParam.eSearchStatus = MXD_RTN_OK;
					if( pDevice->m_fnCallbacks.OnServiceSearchResult )
						pDevice->m_fnCallbacks.OnServiceSearchResult( pDevice->nDemodChipIndex, pDevice->ServiceSearchParam.pSearchUserParam, pDevice->ServiceSearchParam.nCurrentFreqKhz, NULL, 0 );
				}
			}
			else if( pDevice->ServiceSearchParam.eSearchStatus == MXD_CLCHDATA_OK )
			{
				if(  DCC_GetTickCount( hDevice ) - pDevice->ServiceSearchParam.nRefTick > 3000 ) //time out?
				{
					MXD_DEMUXER_CONTEXT* pDemuxCtx = (MXD_DEMUXER_CONTEXT*)pDevice->pDemuxerPrivateStruct;
					if( pDevice->m_fnCallbacks.OnServiceSearchResult )
						pDevice->m_fnCallbacks.OnServiceSearchResult( pDevice->nDemodChipIndex, pDevice->ServiceSearchParam.pSearchUserParam, pDevice->ServiceSearchParam.nCurrentFreqKhz,  pDemuxCtx->m_pSeviceChannelList,  pDemuxCtx->m_nServiceCount  );
					DTP_StopServiceNameReceive( hDevice );

					//change to next frequency.
					pDevice->ServiceSearchParam.eSearchStatus = MXD_RTN_OK;

					//stop search progress if all frequency scaned.
					if( pDevice->ServiceSearchParam.nCurrentFreqKhz >= pDevice->ServiceSearchParam.nEndFreqKhz )
					{
						MXD_DebugPrint( "Batch frequency search (from %d to %d) finished!\n", pDevice->ServiceSearchParam.nBeginFreqKhz, pDevice->ServiceSearchParam.nEndFreqKhz );
						pDevice->bStartServiceSearch = FALSE;
					}
				}

				eRtnCode = DTP_CheckServiceData(pDevice, &uIndex);
				if (uIndex)
				{
					eRtnCode = DTP_ServiceDataProcess(pDevice, uIndex, TRUE);
					if( eRtnCode == MXD_RTN_OK )
					{
						MXD_DEMUXER_CONTEXT* pDemuxCtx = (MXD_DEMUXER_CONTEXT*)pDevice->pDemuxerPrivateStruct;
						if( pDevice->m_fnCallbacks.OnServiceSearchResult )
							pDevice->m_fnCallbacks.OnServiceSearchResult( pDevice->nDemodChipIndex, pDevice->ServiceSearchParam.pSearchUserParam, pDevice->ServiceSearchParam.nCurrentFreqKhz,   pDemuxCtx->m_pSeviceChannelList,  pDemuxCtx->m_nServiceCount  );
						DTP_StopServiceNameReceive( hDevice );

						//change to next frequency.
						pDevice->ServiceSearchParam.eSearchStatus = MXD_RTN_OK;

						//stop search progress if all frequency scaned.
						if( pDevice->ServiceSearchParam.nCurrentFreqKhz >= pDevice->ServiceSearchParam.nEndFreqKhz )
						{
							MXD_DebugPrint( "Batch frequency search (from %d to %d) finished!\n", pDevice->ServiceSearchParam.nBeginFreqKhz, pDevice->ServiceSearchParam.nEndFreqKhz );
							pDevice->bStartServiceSearch = FALSE;
						}
						else
						{
							//todo: set register to sync the signal in next frequency.
						}
					}
				}
			}
		}
		else if( MXD_TS == pDevice->tDeviceConfig.eDataPath && pDevice->m_fnCallbacks.OnReadTsData && (!pDevice->bStartRecovery) )
		{
			MXD_UINT32 nTsDataLen = 0;
			MXD_UINT8* pTsData = NULL;
			pDevice->m_fnCallbacks.OnReadTsData( pDevice->nDemodChipIndex, &pTsData, &nTsDataLen );
			if( nTsDataLen && pTsData )
				MXD_TSPacketProcess( hDevice, pTsData, nTsDataLen );
		}
	}

	if( !pDevice->bStartServicePlay )
		return MXD_RTN_OK;

	if (MXD_TS == pDevice->tDeviceConfig.eDataPath)
	{
		if( pDevice->m_fnCallbacks.OnReadTsData )
		{
			MXD_UINT32 nTsDataLen = 0;
			MXD_UINT8* pTsData = NULL;
			pDevice->m_fnCallbacks.OnReadTsData( pDevice->nDemodChipIndex, &pTsData, &nTsDataLen );
			if( nTsDataLen && pTsData )
				MXD_TSPacketProcess( hDevice, pTsData, nTsDataLen );
		}
		return MXD_RTN_OK;
	}

	eRtnCode = DTP_CheckServiceData(pDevice, &uIndex);
	if (0 != uIndex)
	{
		eRtnCode = DTP_ServiceDataProcess(pDevice, uIndex, FALSE);
#ifdef FIELDTEST_UPDATEREG
		FieldTestReadReg(1);
#endif
	}
#endif
	return MXD_RTN_OK;
}

/*!
* \par Description
* This function is used get the extended information from Clch which have not retrun from the GetSeviceInfo function.
*
* \param hDevice	[IN] the handle of chip device which host is operating;
* \param pNIT_Info	[OUT] return the information from NIT Table.
*
* \return   
*    MXD_RTN_OK	-	the call succeeded
*
* \warning      
*/
MXD_RETURN_CODE MXD_GetExtendedClchInfo( MXD_HANDLE hDevice, MXD_SYS_NIT_CONF_T* pNIT_Info )
{
	MIRA_DEVICE_HANDLE* pDevice = (MIRA_DEVICE_HANDLE*) hDevice;
	MXD_DEMUXER_CONTEXT* pDemuxCtx = (MXD_DEMUXER_CONTEXT*)pDevice->pDemuxerPrivateStruct;

	MXD_Memcpy( pNIT_Info, &pDemuxCtx->m_sNitInfo, sizeof(pDemuxCtx->m_sNitInfo) );

	return MXD_RTN_OK;
}

/*!
* \par Description
* This function is used to start a esg service channel. this function will return immeditely and specified type's ESG data will come back to the callback functions.
*
* \param hDevice	[IN] the handle of chip device which host is operating;
* \param userParam	[IN]	this parameter will give back to host when SDK call in the callback functions.
* \param nEsgDataTypeId	[IN] the type id of esg data
*
* \return   
*    MXD_RTN_OK	-	the call succeeded
*
* \warning      
*/
MXD_RETURN_CODE MXD_EXPORT MXD_StartEsgRecieving( MXD_HANDLE hDevice, void* userParam, MXD_UINT8 nEsgDataTypeId )
{
	MIRA_DEVICE_HANDLE* pDevice = (MIRA_DEVICE_HANDLE*) hDevice;
	MXD_DEMUXER_CONTEXT* pDemuxCtx = (MXD_DEMUXER_CONTEXT*)pDevice->pDemuxerPrivateStruct;
	MXD_UINT32 j, nEsgSrvId=0;

	for( j=0; j<pDemuxCtx->m_nServiceCount; j++ )
	{
		if( pDemuxCtx->m_pSeviceChannelList[j].eServiceType == MXD_CMMBSERVICE_TYPE_ESG )
		{
			nEsgSrvId = pDemuxCtx->m_pSeviceChannelList[j].nServiceID;
			break;
		}
	}

	if( nEsgSrvId == 0 )
		return MXD_GENERAL_ERROR;

	if( MXD_PlayService( hDevice, nEsgSrvId, userParam ) != MXD_RTN_OK )
		return MXD_GENERAL_ERROR;

	pDemuxCtx->m_nWantEsgDataTypeID = nEsgDataTypeId;

	return MXD_RTN_OK;
}

/*!
* \par Description
* This function is used to stop esg service.
*
* \param hDevice	[IN] the handle of chip device which host is operating;
*
* \return   
*    MXD_RTN_OK	-	the call succeeded
*
* \warning    
*/
MXD_RETURN_CODE MXD_EXPORT MXD_StopEsgRecieving( MXD_HANDLE hDevice )
{
	MIRA_DEVICE_HANDLE* pDevice = (MIRA_DEVICE_HANDLE*) hDevice;
	MXD_DEMUXER_CONTEXT* pDemuxCtx = (MXD_DEMUXER_CONTEXT*)pDevice->pDemuxerPrivateStruct;
	MXD_UINT32 j, nEsgSrvId=0;

	for( j=0; j<pDemuxCtx->m_nServiceCount; j++ )
	{
		if( pDemuxCtx->m_pSeviceChannelList[j].eServiceType == MXD_CMMBSERVICE_TYPE_ESG )
		{
			nEsgSrvId = pDemuxCtx->m_pSeviceChannelList[j].nServiceID;
			break;
		}
	}

	if( nEsgSrvId == 0 )
		return MXD_GENERAL_ERROR;

	if( MXD_StopService( hDevice, nEsgSrvId ) != MXD_RTN_OK )
		return MXD_GENERAL_ERROR;

	pDemuxCtx->m_nWantEsgDataTypeID = 0;
	return MXD_RTN_OK;
}

/*!
* \par Description
* This function used to get CLCH Service data if available
*
* \param hDevice	[IN] the handle of chip device which host is operating;
* \param **ppinfo  [IN] cmmb service info struct pointer
* \param pservice_count [IN] cmmb service count
*
* \return   
*    MXD_RTN_OK	-	the call succeeded
*
* \warning     
*/
MXD_RETURN_CODE DTP_ClchProcess(MXD_HANDLE hDevice, MXD_CMMBSERVICE_INFO **ppinfo, MXD_UINT32* pservice_count)
{
	MIRA_DEVICE_HANDLE* pDevice = (MIRA_DEVICE_HANDLE*) hDevice;
	MXD_RETURN_CODE eRtnCode    = MXD_RTN_OK;
	MXD_UINT32   m_buffLength   = 0;
	// MXD_UINT8    nThisIndex     = 0;
	MXD_UINT8    m_dataIntStatus = 0;
	MXD_UINT16   m_hdataCount   = 0;
	MXD_UINT8	  m_ldataCount   = 0;
	MXD_UINT8    m_intOverflow  = 0;

	MXD_ReadRegFields(pDevice, REG_HIC1_INT_STATUS, 5 , 1, &m_dataIntStatus);

	if (m_dataIntStatus & 0x01)
	{
		//clear interrupt
		MXD_WriteRegFields(pDevice, REG_HIC1_INT_CLEAR, 5, 1, 0x1);
		MXD_EX_ReadReg(pDevice, m_dataAvailReg[5][0], (MXD_UINT8*)&m_hdataCount);
		MXD_EX_ReadReg(pDevice, m_dataAvailReg[5][1], &m_ldataCount);
		m_buffLength = ((m_hdataCount<<8)+ m_ldataCount)*4;
		MXD_EX_ReadReg(pDevice, REG_OTDD_INT_STATUS, &m_intOverflow);		
		if (m_intOverflow & 0x20)
		{
			MXD_DebugPrint("clch data overflow intr:%x\n", m_intOverflow);
			MXD_WriteRegFields(pDevice, REG_OTDD_INT_CLEAR, 5, 1, 0x1);
		}
		if ( 0 == m_buffLength)
		{
			MXD_WriteRegFields(pDevice, REG_HIC1_INT_CLEAR, 5, 1, 0x1);
			MXD_DebugPrint("clch data lenth:%d\n", m_buffLength);
			return MXD_GENERAL_ERROR;
		}
		//		 nThisIndex = pDevice->ActiveService[5].nReadIndex;
		if (m_buffLength <= pDevice->ActiveService[5].nFrameBufLen*2)
		{
			eRtnCode = MXD_BurstRead(pDevice, 1, m_dataReg[5], pDevice->ActiveService[5].nFrameBufLen, pDevice->ActiveService[5].pRawFrameBuffer);
			if (MXD_RTN_OK != eRtnCode)
			{
				MXD_DebugPrint("spi read data err!\n");
				return MXD_GENERAL_ERROR;
			}
			else
			{
				if( DMX_GetServiceInfoList( hDevice, pDevice->ActiveService[5].pRawFrameBuffer, pDevice->ActiveService[5].nFrameBufLen, ppinfo, pservice_count ) != MXD_RTN_OK )
				{
					MXD_DebugPrint("parse clch data err!\n");
					return MXD_GENERAL_ERROR;
				}
				else
				{

				}
			}
		}
		else
		{
			MXD_DebugPrint("CLCH data large!\n");
			return MXD_GENERAL_ERROR;
		}
	}
	else
	{
		//		 MXD_DebugPrint("polling status!!\n");
		return MXD_POLLING_STATUS;
	}
	return MXD_RTN_OK;
}

/*!
* \par Description
* This function used to check Service data if available
*
* \param hDevice	[IN] the handle of chip device which host is operating;
* \param uIntStatus  [IN] the bit of interrupt 
*
* \return   
*    MXD_RTN_OK	-	the call succeeded
*
* \warning     
*/
MXD_RETURN_CODE DTP_CheckServiceData(MXD_HANDLE hDevice, MXD_UINT8* uIntStatus)
{
	MIRA_DEVICE_HANDLE* pDevice = (MIRA_DEVICE_HANDLE*) hDevice;
	MXD_UINT8    m_dataIntStatus   = 0;
	//  MXD_UINT8    m_reconfigStatus  = 0;
	MXD_UINT32   m_buffLength      = 0;
	//  MXD_UINT32   m_resLength        = 0;
	MXD_UINT16   m_hdataCount     = 0;
	MXD_UINT8    m_ldataCount       = 0;
	MXD_UINT8    m_intOverflow     = 0;
	MXD_UINT8    uIndex, i                 = 0, valid;

	MXD_Memset(&uIndex,0, sizeof(MXD_UINT8));
	while(1)
	{		
		MXD_EX_ReadReg(pDevice, REG_HIC1_INT_STATUS, &m_dataIntStatus);
		if (!(m_dataIntStatus&0x3F))
		{
			*uIntStatus = uIndex;
			break;
		}

		for( i= 0; i< 6; i++)
		{
			if ( m_dataIntStatus & (1 << i))
			{
				//clear interrupt
				MXD_WriteRegFields(pDevice, REG_HIC1_INT_CLEAR, i, 1, 0x1);
				MXD_EX_ReadReg(pDevice, REG_OTDD_INT_STATUS, &m_intOverflow);
				if ( m_intOverflow & (1 << i))
				{
					MXD_EX_ReadReg(pDevice, m_dataAvailReg[i][0], (MXD_UINT8*)&m_hdataCount);
					MXD_EX_ReadReg(pDevice, m_dataAvailReg[i][1], &m_ldataCount);
					m_buffLength =((m_hdataCount << 8) + m_ldataCount)*4;
					if ( i < 5)
						MXD_DebugPrint("ch%d-Overflow length:%ld, time:%d\n" ,i,m_buffLength, DCC_GetTickCount(hDevice));  
					//clear overflow interrupt
					MXD_WriteRegFields(pDevice, REG_OTDD_INT_CLEAR, i, 1, 0x1);

					MXD_ReadRegFields( pDevice, REG_SC_VALID_CFG, i, 1, &valid);
					if ( valid )
					{
						MXD_WriteRegFields(pDevice, REG_SC_VALID_CFG, i, 1, 0x0);
						MXD_WriteRegFields(pDevice, REG_SC_VALID_CFG, i, 1, 0x1);
					}
				}
				else
					uIndex = (uIndex|(0x01<<i));
			}

		}
	}
	return MXD_RTN_OK;
}

/*!
* \par Description
* This function used to check service data avialble count
*
* \param hDevice	             [IN] the handle of chip device which host is operating;
* \param Index                    [IN] Channel index 
* \m_AvailabledataLength  [OUT] Available Data Count
*
* \return   
*    MXD_RTN_OK	-	the call succeeded
*
* \warning     
*/

MXD_RETURN_CODE DTP_CheckAvailableDataCount(MXD_HANDLE hDevice, MXD_UINT8 Index, MXD_UINT32*  m_AvailabledataLength)
{
	MXD_UINT32   m_buffLength    = 0;
	MXD_UINT16   m_hdataCount   = 0;
	MXD_UINT8    m_ldataCount     = 0;
	//  MXD_UINT8 * m_regTable        = NULL;
	MIRA_DEVICE_HANDLE* pDevice = (MIRA_DEVICE_HANDLE*) hDevice;
	MXD_EX_ReadReg(pDevice, m_dataAvailReg[Index][0], (MXD_UINT8*)&m_hdataCount);
	MXD_EX_ReadReg(pDevice, m_dataAvailReg[Index][1], &m_ldataCount);
	m_buffLength =((m_hdataCount << 8) + m_ldataCount)*4;

	if (0 == m_buffLength)
	{
		//	MXD_DebugPrint("ch%d aviable count :%d, time:%d\n",Index, m_buffLength, DCC_GetTickCount(hDevice));
		*m_AvailabledataLength = 0;
		return MXD_GENERAL_ERROR;
	}
	if (m_buffLength > pDevice->ActiveService[Index].nBufferLen)
	{
		if (m_buffLength == pDevice->ActiveService[Index].nBufferLen*2)
		{
			*m_AvailabledataLength = pDevice->ActiveService[Index].nBufferLen;
			return MXD_RTN_OK;
		}
		MXD_DebugPrint("ch%d large data length:%ld, time:%d\n",Index, m_buffLength, DCC_GetTickCount(hDevice)); 
		*m_AvailabledataLength = 0;
		return MXD_GENERAL_ERROR;
	}
	*m_AvailabledataLength = m_buffLength;
	return MXD_RTN_OK;
}
/*!
* \par Description
* This function used to process service data
*
* \param hDevice	[IN] the handle of chip device which host is operating;
* \param uIndex     [IN] service index 
*
* \return   
*    MXD_RTN_OK	-	the call succeeded
*
* \warning     
*/

MXD_RETURN_CODE DTP_ServiceDataProcess(MXD_HANDLE hDevice, MXD_UINT8 uIndex, MXD_BOOL bGetServiceName)
{
	MIRA_DEVICE_HANDLE* pDevice = (MIRA_DEVICE_HANDLE*) hDevice;
	MXD_RETURN_CODE eRtnCode = MXD_GENERAL_ERROR;
	MXD_UINT32   m_buffLength  = 0,tm;
	MXD_UINT8    uTempIndex = 0;
	MXD_UINT8    index =0;
	MXD_UINT8    j = 0;//,k = 0;
	MXD_UINT32   nThisIndex = 0;
	MXD_UINT8    bufferAddr = 0;

	for (j = 0; j < 6; j++)  //Loop 0~5 SC
	{
		if ( !pDevice->bCLCHEnable && j==5)
			continue;
		uTempIndex = (uIndex&(0x01<<j));
		if  (uTempIndex)
		{
			index = j;
			bufferAddr = m_dataReg[j];
			eRtnCode  = DTP_CheckAvailableDataCount(pDevice, index, &m_buffLength);
			if ( MXD_RTN_OK != eRtnCode)
				continue;
		}
		else
			continue;
		//	nThisIndex = pDevice->ActiveService[index].nReadIndex;
		if (NULL == pDevice->ActiveService[index].pRawFrameBuffer)
		{
			continue;
		}
DTP_READ_DATA:
		if( m_buffLength == pDevice->ActiveService[index].nFrameBufLen*2 )
			m_buffLength = pDevice->ActiveService[index].nFrameBufLen;
		if ( m_buffLength <= pDevice->ActiveService[index].nFrameBufLen)
		{	
			if (pDevice->ActiveService[index].pFrameBufferTail + m_buffLength == pDevice->ActiveService[index].pRawFrameBuffer + pDevice->ActiveService[index].nFrameBufLen)
			{
				tm = DCC_GetTickCount(hDevice);
				eRtnCode = MXD_BurstRead(pDevice, 1, bufferAddr, m_buffLength, pDevice->ActiveService[index].pFrameBufferTail);
				MXD_DebugPrint("ch %d read data 1:%d --- %x %x %x %x, time:%d, spend:%d\n",index, m_buffLength, *(pDevice->ActiveService[index].pFrameBufferTail),*(pDevice->ActiveService[index].pFrameBufferTail+1),
					*(pDevice->ActiveService[index].pFrameBufferTail+2), *(pDevice->ActiveService[index].pFrameBufferTail+3),DCC_GetTickCount(hDevice), DCC_GetTickCount(hDevice)-tm);

				if( 0x01000000!=*(MXD_UINT32*)(pDevice->ActiveService[index].pRawFrameBuffer) && !pDevice->ActiveService[index].bCorrectDataGot )
				{
					MXD_UINT8 valid;
					MXD_ReadRegFields( pDevice, REG_SC_VALID_CFG, index, 1, &valid);
					if ( valid )
					{
						MXD_WriteRegFields(pDevice, REG_SC_VALID_CFG, index, 1, 0x0);
						MXD_WriteRegFields(pDevice, REG_SC_VALID_CFG, index, 1, 0x1);
					}
				}
				else
				{
					pDevice->ActiveService[index].bCorrectDataGot = TRUE;
				}

				pDevice->ActiveService[index].pFrameBufferTail = pDevice->ActiveService[index].pRawFrameBuffer + m_buffLength;
				if (pDevice->ActiveService[index].pFrameBufferTail == pDevice->ActiveService[index].pRawFrameBuffer + pDevice->ActiveService[index].nFrameBufLen)
				{
					CB_OnRawFrame                   OnRawFrame = ((MIRA_DEVICE_HANDLE*)hDevice)->m_fnCallbacks.OnRawFrame;
					MXD_DEMUXER_CONTEXT* pContext = (MXD_DEMUXER_CONTEXT*)((MIRA_DEVICE_HANDLE*)hDevice)->pDemuxerPrivateStruct;
					void* pSeviceUserParam;
					MXD_BOOL bSkipDemux = FALSE;
					if( !bGetServiceName )
					{
						// send this index buffer
						if (5 == index )
						{
							if (OnRawFrame)
							{
								if (OnRawFrame(((MIRA_DEVICE_HANDLE*)hDevice)->nDemodChipIndex, 0, 0, pDevice->ActiveService[index].pRawFrameBuffer,  pDevice->ActiveService[index].nFrameBufLen) == MXD_DEMUXER_STOP)
									bSkipDemux = TRUE;
							}
							if( !bSkipDemux )
								eRtnCode = DMX_FeedControlFrameData(pDevice,  pDevice->ActiveService[index].pRawFrameBuffer,  pDevice->ActiveService[index].nFrameBufLen);
						}
						else
						{
							if (!Context_GetUserParam(pContext, pDevice->ActiveService[index].nActiveServiceID, &pSeviceUserParam))
								pSeviceUserParam = (void*) - 1;

							if (OnRawFrame)
							{
								if (OnRawFrame(((MIRA_DEVICE_HANDLE*)hDevice)->nDemodChipIndex, pDevice->ActiveService[index].nActiveServiceID, pSeviceUserParam, pDevice->ActiveService[index].pRawFrameBuffer,  pDevice->ActiveService[index].nFrameBufLen) == MXD_DEMUXER_STOP)
									bSkipDemux = TRUE;
							}

							if( !bSkipDemux )
							{
								if ((eRtnCode = DMX_FeedServiceFrameData(pDevice, pDevice->ActiveService[index].nActiveServiceID, pDevice->ActiveService[index].pRawFrameBuffer, pDevice->ActiveService[index].nFrameBufLen)) == MXD_GENERAL_ERROR)
									MXD_DebugPrint("service data error!\n");
							}
						}
					}
					else
					{
						// send esg buffer to demuxer to got service name. here assume only esg service is actived.
						MXD_CMMBSERVICE_INFO *psvrInfos;
						MXD_UINT32 servicecount;
						if( (eRtnCode = DMX_GetServiceNameFromEsg(pDevice, pDevice->ActiveService[index].pRawFrameBuffer, pDevice->ActiveService[index].nFrameBufLen, &psvrInfos, &servicecount)) == MXD_GENERAL_ERROR )
							MXD_DebugPrint( "esg data error!\n" );
					}
					pDevice->ActiveService[index].pFrameBufferTail = pDevice->ActiveService[index].pRawFrameBuffer;
				}
				else
					pDevice->ActiveService[index].pFrameBufferTail = pDevice->ActiveService[index].pRawFrameBuffer;
				if (pDevice->ActiveService[index].pFrameBufferTail > (pDevice->ActiveService[index].pRawFrameBuffer + pDevice->ActiveService[index].nFrameBufLen))
					MXD_DebugPrint( "Mem out of limit!\n" );
				//pDevice->ActiveService[index].nReadIndex = nThisIndex;

			}
			else
			{
				//m_resLength = pDevice->ActiveService[index].pRawFrameBuffer[nThisIndex] + pDevice->ActiveService[index].nFrameBufLen - pDevice->ActiveService[index].pFrameBufferTail;
				//nThisIndex = (nThisIndex + 1)%2;
				//read all the data to next buffer
				eRtnCode = MXD_BurstRead(pDevice, 1, bufferAddr, m_buffLength , pDevice->ActiveService[index].pRawFrameBuffer);	
				MXD_DebugPrint("ch%d read data2 %d :%d --- %x %x %x %x, time:%d\n",index,nThisIndex, m_buffLength, *(pDevice->ActiveService[index].pRawFrameBuffer),*(pDevice->ActiveService[index].pRawFrameBuffer+1),
					*(pDevice->ActiveService[index].pRawFrameBuffer+2), *(pDevice->ActiveService[index].pRawFrameBuffer+3),DCC_GetTickCount(hDevice));

				if( 0x01000000!=*(MXD_UINT32*)(pDevice->ActiveService[index].pRawFrameBuffer) && !pDevice->ActiveService[index].bCorrectDataGot )
				{
					MXD_UINT8 valid;
					MXD_ReadRegFields( pDevice, REG_SC_VALID_CFG, index, 1, &valid);
					if ( valid )
					{
						MXD_WriteRegFields(pDevice, REG_SC_VALID_CFG, index, 1, 0x0);
						MXD_WriteRegFields(pDevice, REG_SC_VALID_CFG, index, 1, 0x1);
					}
				}
				else
				{
					pDevice->ActiveService[index].bCorrectDataGot = TRUE;
				}

				//      nThisIndex = (nThisIndex + 1)%2;
				if (pDevice->ActiveService[index].pFrameBufferTail > pDevice->ActiveService[index].pRawFrameBuffer + pDevice->ActiveService[index].nFrameBufLen)
					MXD_DebugPrint( "mem out of limit!\n" );
			}
		}

		if (uTempIndex && pDevice->ActiveService[index].nActiveServiceID)
		{
			DTP_CheckAvailableDataCount(pDevice, index, &m_buffLength);

			if (m_buffLength == pDevice->ActiveService[index].nFrameBufLen)
			{
				MXD_DebugPrint("remain one frame, read again! %d\n", DCC_GetTickCount(hDevice));
				goto DTP_READ_DATA;
			}

			if (m_buffLength > 0)
			{
				MXD_DebugPrint("!!!!!!!!!!!!!!remain data length after read: %d, time: %d\n", m_buffLength, DCC_GetTickCount(hDevice));
			}
		}
	}
	return eRtnCode;
}


/*!
* \par Description
* This function used to get chip system status.
*
* \param hDevice	[IN] the handle of chip device which host is operating;
* \param sys_status	[OUT]	the system status.
*
* \return   
*    MXD_RTN_OK	-	the call succeeded
*
* \warning     
*/
MXD_RETURN_CODE MXD_EXPORT MXD_GetSystemStatus( MXD_HANDLE hDevice, MXD_SYS_STATUS *sys_status )
{
	MIRA_DEVICE_HANDLE* pDevice = (MIRA_DEVICE_HANDLE*) hDevice;	
	MXD_SYS_STATUS dcc_sys_status ;
	if( (NULL == pDevice)||( NULL == sys_status ) )
	{
		return MXD_GENERAL_ERROR;
	}
	sys_status->bLock = pDevice->bSystemLockStatus;
	sys_status->nCurrentFrequency = pDevice->ServiceSearchParam.nCurrentFreqKhz*1000;

	sys_status->nSignalNoiseRatio = DCC_GetSystemSnr( pDevice,&dcc_sys_status);
	sys_status->nSignalStrength = dcc_sys_status.nSignalStrength;
	sys_status->nLdpcErrPercent = dcc_sys_status.nLdpcErrPercent;
	sys_status->nLdpcWindow = dcc_sys_status.nLdpcWindow;
	if(sys_status->nRSErrCount==1)
		DTP_GetRSErr(pDevice,&(sys_status->nRSErrCount));
	sys_status->bRecoveryStatus = pDevice->bRecoveryStatus;
	return MXD_RTN_OK;
}

/*!
* \par Description
* This function only used when Mpeg2TS interface is enabled. It will demux received Mpeg2TS packet data and call registed callback functions .
* Notice: host must pass in received data from the TS interface without any process!
*
* \param hDevice	[IN] the handle of chip device which host is operating;
* \param tsData	[IN] the mpeg2 ts data;
* \param dataSize	[IN] the data size;
*
* \return   
*    MXD_RTN_OK	-	the call succeeded
*
* \warning     
*/
MXD_RETURN_CODE MXD_EXPORT MXD_TSPacketProcess( MXD_HANDLE hDevice, MXD_UINT8* tsData, MXD_UINT32 dataSize )
{
	MIRA_DEVICE_HANDLE* pDevice = (MIRA_DEVICE_HANDLE*) hDevice;
	MXD_UINT32 nIndex=0;
	MXD_INT32 nActiveIndex=0;
	MXD_UINT8 nTsPayloadLen=186 , i;
	static MIRA_SEARCH_RESULT resSearch = FREQ_SEARCH_FAIL;

	for( nIndex=1; nIndex<dataSize; nIndex+=188 )
	{
		nTsPayloadLen=186;
		nActiveIndex = tsData[nIndex] & 0xF;
		if( nActiveIndex > 5 )
		{
			MXD_DebugPrint( "Unexpected ts block index got %x!\n", tsData[nIndex] );
			continue;
		}
		if( pDevice->ActiveService[nActiveIndex].nActiveServiceID != 0 )
		{
			if( (tsData[nIndex] & 0x20) == 0x20 ) //is interleave block start?
			{
				if( tsData[nIndex+1] == 0 && tsData[nIndex+2] == 0 && tsData[nIndex+3] == 0 && tsData[nIndex+4] == 1 )
				{
					//frame header begin got? refill buffer from beginning.
					MXD_DebugPrint( "Frame header got, sc %d, id %x!\n", nActiveIndex, pDevice->ActiveService[nActiveIndex].nActiveServiceID );
					pDevice->ActiveService[nActiveIndex].pFrameBufferTail = pDevice->ActiveService[nActiveIndex].pRawFrameBuffer;
				}
				else
				{
					//	MXD_DebugPrint( "\tItlv header got, sc %d, id %x, %x %x %x %x !\n", nActiveIndex, pDevice->ActiveService[nActiveIndex].nActiveServiceID, tsData[nIndex+1], tsData[nIndex+2], tsData[nIndex+3], tsData[nIndex+4] );
				}
				//refill the buffer from beginning
				if( pDevice->ActiveService[nActiveIndex].pFrameBufferTail + 186 > pDevice->ActiveService[nActiveIndex].pRawFrameBuffer + pDevice->ActiveService[nActiveIndex].nFrameBufLen )
				{
					//unexpect begin before passing to demuxer? refill buffer from beginning.
					//		MXD_DebugPrint( "Unexpected ts block starting got!\n" );
					pDevice->ActiveService[nActiveIndex].pFrameBufferTail = pDevice->ActiveService[nActiveIndex].pRawFrameBuffer;
				}
				MXD_Memcpy( pDevice->ActiveService[nActiveIndex].pFrameBufferTail, tsData + nIndex + 1, 186 );
				pDevice->ActiveService[nActiveIndex].pFrameBufferTail += 186;
				continue;
			}
			else
			{
				if( pDevice->ActiveService[nActiveIndex].pFrameBufferTail == pDevice->ActiveService[nActiveIndex].pRawFrameBuffer )
					continue; //frame header have not filled, throw data

				if( (tsData[nIndex] & 0x10) == 0x10 ) //is interleave block end?
				{
					if( nActiveIndex == 5 )
						nTsPayloadLen = 84;
					else
					{
						MXD_UINT32 nItvBlockLen=0;
						MXD_DEMUXER_CONTEXT* pDemuxCtx = (MXD_DEMUXER_CONTEXT*)pDevice->pDemuxerPrivateStruct;
						for( i=0; i<pDemuxCtx->m_nServiceCount; i++ )
						{
							if( pDevice->ActiveService[nActiveIndex].nActiveServiceID == pDemuxCtx->m_pSeviceChannelList[i].nServiceID )
							{
								nItvBlockLen = ((MXD_UINT32) ( (pDemuxCtx->m_pSeviceChannelList[i].eLdpcMode == MXD_LDPC_MODE_1_DIV_2 ? 8640 : 12960 ) 
									* (pDemuxCtx->m_pSeviceChannelList[i].eModuType == MXD_MODULATE_TYPE_BPSK ? 1 : (pDemuxCtx->m_pSeviceChannelList[i].eModuType == MXD_MODULATE_TYPE_QPSK ? 2 : 4) ) 
									* (pDemuxCtx->m_pSeviceChannelList[i].eRsMode == MXD_RS_MODE_240_240 ? 1 : (pDemuxCtx->m_pSeviceChannelList[i].eRsMode == MXD_RS_MODE_240_224 ? 224.0/240.0 : (pDemuxCtx->m_pSeviceChannelList[i].eRsMode == MXD_RS_MODE_240_192 ? 192.0/240.0 : 176.0/240.0) ) ) ) );
								switch( pDemuxCtx->m_pSeviceChannelList[i].eInterleaveMode )
								{
								case MXD_INTERLEAVE_MODE_MODE_1:
									nItvBlockLen = (pDemuxCtx->m_pSeviceChannelList[i].eModuType == MXD_MODULATE_TYPE_BPSK ? nItvBlockLen*2 : (pDemuxCtx->m_pSeviceChannelList[i].eModuType == MXD_MODULATE_TYPE_QPSK ? nItvBlockLen : nItvBlockLen/2) );
									break;
								case MXD_INTERLEAVE_MODE_MODE_2:
									nItvBlockLen = (pDemuxCtx->m_pSeviceChannelList[i].eModuType == MXD_MODULATE_TYPE_BPSK ? nItvBlockLen*4 : (pDemuxCtx->m_pSeviceChannelList[i].eModuType == MXD_MODULATE_TYPE_QPSK ? nItvBlockLen*2 : nItvBlockLen) );
									break;
								case MXD_INTERLEAVE_MODE_MODE_3:
									nItvBlockLen = (pDemuxCtx->m_pSeviceChannelList[i].eModuType == MXD_MODULATE_TYPE_BPSK ? nItvBlockLen*8 : (pDemuxCtx->m_pSeviceChannelList[i].eModuType == MXD_MODULATE_TYPE_QPSK ? nItvBlockLen*4 : nItvBlockLen*2) );
									break;
								}
								break;
							}
						}
						nTsPayloadLen = nItvBlockLen%186;
					}
				}
			}

			if( pDevice->ActiveService[nActiveIndex].pFrameBufferTail + nTsPayloadLen > pDevice->ActiveService[nActiveIndex].pRawFrameBuffer + pDevice->ActiveService[nActiveIndex].nFrameBufLen )
			{
				//expect tail but not got? full fill buffer and pass it to demuxer.
				MXD_DebugPrint( "Unexpected ts block end got!\n" );
				nTsPayloadLen = pDevice->ActiveService[nActiveIndex].nFrameBufLen - (pDevice->ActiveService[nActiveIndex].pFrameBufferTail - pDevice->ActiveService[nActiveIndex].pRawFrameBuffer );
			}

			MXD_Memcpy( pDevice->ActiveService[nActiveIndex].pFrameBufferTail, tsData + nIndex + 1, nTsPayloadLen );
			pDevice->ActiveService[nActiveIndex].pFrameBufferTail += nTsPayloadLen;

			//MXD_DebugPrint( "ts atv=%d, %d,%d\n", nActiveIndex, pDevice->ActiveService[nActiveIndex].pFrameBufferTail - pDevice->ActiveService[nActiveIndex].pRawFrameBuffer, nTsPayloadLen );
			if( pDevice->ActiveService[nActiveIndex].pFrameBufferTail - pDevice->ActiveService[nActiveIndex].pRawFrameBuffer == pDevice->ActiveService[nActiveIndex].nFrameBufLen )
			{
#ifdef STATEMACHINE
				CB_OnRawFrame                   OnRawFrame = ((MIRA_DEVICE_HANDLE*)hDevice)->m_fnCallbacks.OnRawFrame;
				MXD_DEMUXER_CONTEXT* pContext = (MXD_DEMUXER_CONTEXT*)((MIRA_DEVICE_HANDLE*)hDevice)->pDemuxerPrivateStruct;
				void* pSeviceUserParam;
				MXD_BOOL bSkipDemux = FALSE;
				if( 0x01000000!=*(MXD_UINT32*)(pDevice->ActiveService[nActiveIndex].pRawFrameBuffer) && !pDevice->ActiveService[nActiveIndex].bCorrectDataGot )
				{
					MXD_UINT8 valid;
					MXD_ReadRegFields( pDevice, REG_SC_VALID_CFG, nActiveIndex, 1, &valid);
					if ( valid )
					{
						MXD_WriteRegFields(pDevice, REG_SC_VALID_CFG, nActiveIndex, 1, 0x0);
						MXD_WriteRegFields(pDevice, REG_SC_VALID_CFG, nActiveIndex, 1, 0x1);
					}
				}
				else
				{
					pDevice->ActiveService[nActiveIndex].bCorrectDataGot = TRUE;
				}

				if( pDevice->eCurrentState == MIRASTATE_GETCLCH && nActiveIndex == 5 )
				{
					MXD_CMMBSERVICE_INFO *psvrInfos;
					MXD_UINT32 servicecount;
					if( DMX_GetServiceInfoList( hDevice, pDevice->ActiveService[5].pRawFrameBuffer, pDevice->ActiveService[5].nFrameBufLen, &psvrInfos, &servicecount ) == MXD_RTN_OK )
					{
						// when service name function actived, search work will not stop until the service name received from esg.
						if( pDevice->ServiceSearchParam.bGetServiceName )
						{
							STE_RequestChangeState( hDevice, MIRASTATE_STARTESG, NULL );
						}
						else
						{
							resSearch = FREQ_SEARCH_OK;
							STE_RequestChangeState( hDevice, MIRASTATE_SEARCHDONE, &resSearch );
						}
						pDevice->ActiveService[nActiveIndex].pFrameBufferTail = pDevice->ActiveService[nActiveIndex].pRawFrameBuffer;
						return MXD_RTN_OK; 
					}
					else
					{
						MXD_DebugPrint("clch data err %x %x %x %x!\n", pDevice->ActiveService[5].pRawFrameBuffer[0], pDevice->ActiveService[5].pRawFrameBuffer[1], pDevice->ActiveService[5].pRawFrameBuffer[2], pDevice->ActiveService[5].pRawFrameBuffer[3] );
						resSearch = FREQ_SEARCH_FAIL;
						STE_RequestChangeState( hDevice, MIRASTATE_SEARCHDONE, &resSearch );
					}
				}
				else if( pDevice->eCurrentState == MIRASTATE_ESGRECEIVING && nActiveIndex == 0 )
				{
					// send esg buffer to demuxer to got service name. here assume only esg service is actived.
					MXD_CMMBSERVICE_INFO *psvrInfos;
					MXD_UINT32 servicecount;
					if( DMX_GetServiceNameFromEsg(pDevice, pDevice->ActiveService[nActiveIndex].pRawFrameBuffer, pDevice->ActiveService[nActiveIndex].nFrameBufLen, &psvrInfos, &servicecount) == MXD_GENERAL_ERROR )
					{
						MXD_DebugPrint( "esg data error!\n" );
						if(  DCC_GetTickCount( hDevice ) - pDevice->ServiceSearchParam.nRefTick > 3000 ) //time out?
						{
							resSearch = FREQ_SEARCH_OK;
							STE_RequestChangeState( hDevice, MIRASTATE_SEARCHDONE, &resSearch );
							pDevice->ActiveService[nActiveIndex].pFrameBufferTail = pDevice->ActiveService[nActiveIndex].pRawFrameBuffer;
							return MXD_RTN_OK; 
						}
					}
					else
					{
						resSearch = FREQ_SEARCH_OK;
						STE_RequestChangeState( hDevice, MIRASTATE_SEARCHDONE, &resSearch );
						pDevice->ActiveService[nActiveIndex].pFrameBufferTail = pDevice->ActiveService[nActiveIndex].pRawFrameBuffer;
						return MXD_RTN_OK; 
					}
				}
				else if( nActiveIndex != 5 )
				{
					if (!Context_GetUserParam(pContext, pDevice->ActiveService[nActiveIndex].nActiveServiceID, &pSeviceUserParam))
						pSeviceUserParam = (void*) - 1;

					if (OnRawFrame)
					{
						if (OnRawFrame(((MIRA_DEVICE_HANDLE*)hDevice)->nDemodChipIndex, pDevice->ActiveService[nActiveIndex].nActiveServiceID, pSeviceUserParam, pDevice->ActiveService[nActiveIndex].pRawFrameBuffer,  pDevice->ActiveService[nActiveIndex].nFrameBufLen) == MXD_DEMUXER_STOP)
							bSkipDemux = TRUE;
					}

					if( !bSkipDemux )
					{
						if (DMX_FeedServiceFrameData(pDevice, pDevice->ActiveService[nActiveIndex].nActiveServiceID, pDevice->ActiveService[nActiveIndex].pRawFrameBuffer, pDevice->ActiveService[nActiveIndex].nFrameBufLen) != MXD_RTN_OK)
							MXD_DebugPrint("service data error %x %x %x %x\n", pDevice->ActiveService[nActiveIndex].pRawFrameBuffer[0], pDevice->ActiveService[nActiveIndex].pRawFrameBuffer[1], pDevice->ActiveService[nActiveIndex].pRawFrameBuffer[2], pDevice->ActiveService[nActiveIndex].pRawFrameBuffer[3]);
					}
				}
				else
				{
					if (OnRawFrame)
					{
						if (OnRawFrame(((MIRA_DEVICE_HANDLE*)hDevice)->nDemodChipIndex, 0, 0, pDevice->ActiveService[nActiveIndex].pRawFrameBuffer,  pDevice->ActiveService[nActiveIndex].nFrameBufLen) == MXD_DEMUXER_STOP)
							bSkipDemux = TRUE;
					}
					if( !bSkipDemux )
					{
						if (DMX_FeedControlFrameData(pDevice, pDevice->ActiveService[nActiveIndex].pRawFrameBuffer, pDevice->ActiveService[nActiveIndex].nFrameBufLen) == MXD_GENERAL_ERROR)
							MXD_DebugPrint("clch data error %x %x %x %x\n", pDevice->ActiveService[nActiveIndex].pRawFrameBuffer[0], pDevice->ActiveService[nActiveIndex].pRawFrameBuffer[1], pDevice->ActiveService[nActiveIndex].pRawFrameBuffer[2], pDevice->ActiveService[nActiveIndex].pRawFrameBuffer[3]);
					}
				}

				pDevice->ActiveService[nActiveIndex].pFrameBufferTail = pDevice->ActiveService[nActiveIndex].pRawFrameBuffer;
#else
#endif
			}
		}
	}
	return MXD_RTN_OK;
}

/*!
* \par Description
* Read tuner register value.
* Set Power Management.
*
* \param hDevice	[IN] the handle of chip device which host is operating;
* \param pm	[IN]	mode of power management, MXD_PM_SUSPEND or MXD_PM_RESUME.
*
* \return   
*    MXD_RTN_OK	-	the call succeeded
*
* \warning     
*/
MXD_RETURN_CODE MXD_EXPORT MXD_SetPowerManagement( MXD_HANDLE hDevice, MXD_PM_MODE pm )
{
	return MXD_RTN_OK;
}

/*!
* \par Description
* Write register value.
*
* \param hDevice	[IN] the handle of chip device which host is operating;
* \param regAddr	[IN]	the address of register.
* \param regValue	[IN]	the value of this register.
*
* \warning     
*/
MXD_RETURN_CODE MXD_EXPORT MXD_EX_WriteReg( MXD_HANDLE hDevice, MXD_UINT8 regAddr, MXD_UINT8 regValue)
{
	MIRA_DEVICE_HANDLE* pDevice = (MIRA_DEVICE_HANDLE*) hDevice;
	MXD_RETURN_CODE eRtnCode = MXD_GENERAL_ERROR;
	switch( pDevice->tDeviceConfig.eControlPath )
	{
	case 0:
		eRtnCode = MxdPorting_I2C_Write( pDevice->nDemodChipIndex, pDevice->tDeviceConfig.nI2cSlaveAddress, regAddr, &regValue );
		break;
	case 1:
		eRtnCode = DDS_SpiCmd52( hDevice, CTRL_PATH_WRITEREG, REG_PAGE_FUNC1, regAddr, &regValue );
		break;
	default:
		return MXD_GENERAL_ERROR;
	}
	return eRtnCode;
}

/*!
* \par Description
* Read register value.
*
* \param hDevice	[IN] the handle of chip device which host is operating;
* \param regAddr	[IN]	the address of register.
* \param regValue	[OUT]	the value of this register.
*
* \return   
*    MXD_RTN_OK	-	the call succeeded
*
* \warning     
*/
MXD_RETURN_CODE MXD_EXPORT MXD_EX_ReadReg( MXD_HANDLE hDevice, MXD_UINT8 regAddr, MXD_UINT8* regValue )
{
	MIRA_DEVICE_HANDLE* pDevice = (MIRA_DEVICE_HANDLE*) hDevice;
	MXD_RETURN_CODE eRtnCode = MXD_GENERAL_ERROR;
	switch( pDevice->tDeviceConfig.eControlPath )
	{
	case 0:
		eRtnCode = MxdPorting_I2C_Read( pDevice->nDemodChipIndex, pDevice->tDeviceConfig.nI2cSlaveAddress, regAddr, regValue );
		break;
	case 1:
		eRtnCode = DDS_SpiCmd52( hDevice, CTRL_PATH_READREG, REG_PAGE_FUNC1, regAddr, regValue );
		break;
	default:
		return MXD_GENERAL_ERROR;
	}
	return eRtnCode;
}

/*!
* \par Description
* Read tuner register value.
*
* \param hDevice	[IN] the handle of chip device which host is operating;
* \param regAddr	[IN]	the address of tuner register.
* \param regValue	[OUT]	the value of this tuner register.
*
* \return   
*    MXD_RTN_OK	-	the call succeeded
*
* \warning     
*/
MXD_RETURN_CODE MXD_EXPORT MXD_EX_ReadTunerReg( MXD_HANDLE hDevice, MXD_UINT8 regAddr, MXD_UINT8* regValue )
{
	MIRA_DEVICE_HANDLE* pDevice = (MIRA_DEVICE_HANDLE*) hDevice;
	MXD_RETURN_CODE eRtnCode = MXD_GENERAL_ERROR;
	MXD_UINT8 ticStatus = 0;
	// MXD_UINT8 checkNum = 0;
	MXD_UINT8 count = 0;
	//  MXD_UINT8 regVal = 0;
	MXD_UINT8 burstLen = 1;
	MXD_UINT32 tick;
	MXD_UINT32 err_count = 0;
	if( (1 == pDevice->tDeviceConfig.bTunerI2cBypass)&&(0 == pDevice->tDeviceConfig.eControlPath) )
	{
		MXD_WriteRegFields( hDevice, REG_SDIO_I2C_CTRL, 0x7,1,0x1);//enable i2c bypass to tic;
		eRtnCode = MxdPorting_I2C_Read( pDevice->nDemodChipIndex, TUNER_SLAVE_ADDR, regAddr, regValue );
		MXD_WriteRegFields( hDevice, REG_SDIO_I2C_CTRL, 0x7,1,0x0);
	}
	else if( (1 == pDevice->tDeviceConfig.bTunerI2cBypass)&&(0 != pDevice->tDeviceConfig.eControlPath) )
	{
		eRtnCode = MXD_GENERAL_ERROR;
	}
	else
	{
		/*control by tic*/
		/* write the read byte number */
		MXD_WriteRegFields( hDevice, REG_TIC_HOST_ACCESS_BYTE_NUM, 0x0, 3, burstLen );
		/*
		MXD_EX_ReadReg(hDevice, tic_host_access_byte_num, &regVal);
		regVal = ( regVal & 0xf8 ) | burstLen;
		MXD_EX_WriteReg( hDevice, tic_host_access_byte_num, regVal );
		*/
		/*write the register address to TIC address reg*/
		MXD_EX_WriteReg( hDevice, REG_SLAVE_RDADD, regAddr);

		/*
		* we can read the TIC status reg to check this read operation completed or not in TIC module
		* if ok, then we read the data reg to get the register value
		*/

		tick = DCC_GetTickCount( hDevice );
		while( DCC_GetTickCount( hDevice ) - tick < 200 )
		{
			eRtnCode = MXD_EX_ReadReg( hDevice, REG_TIC_STATUS, &ticStatus);
			if( MXD_RTN_OK == eRtnCode )
			{
				if( 0 != (ticStatus & 0x01))/* check bit0 of ticStatus ,if it is '1b1, then ok.*/
				{
					for(count = 0; count < burstLen; count++ )
					{
						eRtnCode = MXD_EX_ReadReg( hDevice,  (REG_SLAVE_RDDATA_A - count), (regValue+count));
						if (MXD_RTN_OK != eRtnCode)
						{
							continue;
						}
					}
					return eRtnCode;/* read tuner reg ok*/
				}
			}/*end of check operStatus*/	
			err_count++;
			if (err_count > 2000)
			{
				MXD_DebugPrint("read tic err!\n");
				break;
			}
		}/*end of for loop*/
		MXD_DebugPrint( "MXD_EX_ReadTunerReg:: read the tic status time out, time is:%d!!!\n",DCC_GetTickCount( hDevice ) - tick );
		eRtnCode =  MXD_GENERAL_ERROR;    
	}
	return eRtnCode;
}

/*!
* \par Description
* Write tuner register value.
*
* \param hDevice	[IN] the handle of chip device which host is operating;
* \param regAddr	[IN]	the address of tuner register.
* \param regValue	[IN]	the value of want to write.
*
* \return   
*    MXD_RTN_OK	-	the call succeeded
*
* \warning     
*/
MXD_RETURN_CODE MXD_EXPORT MXD_EX_WriteTunerReg( MXD_HANDLE hDevice, MXD_UINT8 regAddr, MXD_UINT8 regValue  )
{
	MIRA_DEVICE_HANDLE* pDevice = (MIRA_DEVICE_HANDLE*) hDevice;
	MXD_RETURN_CODE eRtnCode = MXD_GENERAL_ERROR;
	MXD_UINT8 ticStatus = 0;
	//   MXD_UINT8 checkNum = 0;
	MXD_UINT8 count = 0;
	MXD_UINT8 burstLen = 1;
	MXD_UINT32 tick;

	if( (1 == pDevice->tDeviceConfig.bTunerI2cBypass)&&(0 == pDevice->tDeviceConfig.eControlPath) )
	{
		MXD_WriteRegFields( hDevice, REG_SDIO_I2C_CTRL, 0x7,1,0x1);//enable i2c bypass to tic;
		eRtnCode = MxdPorting_I2C_Write( pDevice->nDemodChipIndex, TUNER_SLAVE_ADDR, regAddr, &regValue );
		MXD_WriteRegFields( hDevice, REG_SDIO_I2C_CTRL, 0x7,1,0x0);
	}
	else if( (1 == pDevice->tDeviceConfig.bTunerI2cBypass)&&(0 != pDevice->tDeviceConfig.eControlPath) )
	{
		eRtnCode = MXD_GENERAL_ERROR;
	}
	else
	{
		/*control by tic*/
		/* write the write byte number */
		MXD_WriteRegFields( hDevice, REG_TIC_HOST_ACCESS_BYTE_NUM, 0x3, 3, burstLen );
		/*
		MXD_EX_ReadReg(hDevice, tic_host_access_byte_num, &regVal);
		regVal = ( regVal & 0xc7 ) | (MXD_UINT8)(burstLen<<3);
		MXD_EX_WriteReg( hDevice, tic_host_access_byte_num, regVal );
		*/
		/* write the register value to TIC write data reg*/
		for(count = 0; count < burstLen; count++ )
		{
			MXD_EX_WriteReg( hDevice,  (REG_SLAVE_WRDATA_A - count), *(&regValue +count));
		}

		/* write the register address to TIC write address reg*/
		MXD_EX_WriteReg( hDevice,  REG_SLAVE_WRADD, regAddr );

		/*we can read the TIC status reg to check this write operation completed or not*/
		tick = DCC_GetTickCount( hDevice );
		while( DCC_GetTickCount( hDevice ) - tick < 200 )
		{
			eRtnCode = MXD_EX_ReadReg( hDevice, REG_TIC_STATUS, &ticStatus );
			if( MXD_RTN_OK == eRtnCode )
			{
				if( 0 !=(ticStatus & 0x01) ) /* check bit0 of ticStatus, if it is '1b1, then ok.*/
				{
					return eRtnCode; /* write tuner reg ok*/
				}
			}/* end of check operStatus */
		}/* end of for loop */
		MXD_DebugPrint(  "MXD_EX_WriteTunerReg:: read the tic status time out, time is:%d!!!\n",DCC_GetTickCount( hDevice ) - tick );  
		eRtnCode =  MXD_GENERAL_ERROR;    
	}
	return eRtnCode;    
}

/*!
* \par Description
* Write multi register value.
*
* \param hDevice	[IN] the handle of chip device which host is operating;
* \param regAddr	[IN]	the address of register.
* \param data	[IN]	the value of this register.
* \param dataLen	[IN]	the value length.
*
* \warning     
*/
MXD_RETURN_CODE MXD_EXPORT MXD_BurstWriteReg( MXD_HANDLE hDevice, MXD_UINT8 regAddr, MXD_UINT8* data, MXD_UINT32 dataLen )
{
	MIRA_DEVICE_HANDLE* pDevice = (MIRA_DEVICE_HANDLE*) hDevice;
	MXD_RETURN_CODE eRtnCode = MXD_GENERAL_ERROR;
	MXD_UINT32 i;
	switch( pDevice->tDeviceConfig.eControlPath )
	{
	case 0:
		for(i=0;i<dataLen;i++)
		{
			eRtnCode = MxdPorting_I2C_Write( pDevice->nDemodChipIndex, pDevice->tDeviceConfig.nI2cSlaveAddress, regAddr, data+i );
			if( MXD_RTN_OK != eRtnCode )
			{
				return MXD_GENERAL_ERROR;
			}
		}
		break;
	case 1:
		for(i=0;i<dataLen/SPI_BURST_LEN;i++)
		{
			eRtnCode = DDS_SpiCmd53( hDevice, SPI_WRITE_FLAG, BLOCK_MODE, regAddr, SPI_BURST_LEN, data+i*SPI_BURST_LEN);

			if( MXD_RTN_OK != eRtnCode )

			{
				return MXD_GENERAL_ERROR;
			}
		}
		eRtnCode = DDS_SpiCmd53( hDevice, SPI_WRITE_FLAG, BLOCK_MODE, regAddr, (dataLen%SPI_BURST_LEN),data+i*SPI_BURST_LEN ); 

		break;
	default:
		return MXD_GENERAL_ERROR;
	}
	return eRtnCode;
}

/*!
* \par Description
* Burst read from maxscend on-chip buffer.
*
* \param hDevice                        [ in ]          the device hanle.
* \param burstMode             [ in ]          Burst read mode: ( BLOCK_READ and MULTIBYTE_READ ).
* \param bufferAddr            [ in ]          On-chip buffer address to be read.
* \param burstLen                      [ in ]          Length to be read, unit:byte.
* \param pBurstDataIn          [ out ]         Pointer to the burst data after reading.
*
* \return Return code by MXD_RETURN_CODE enumeration.
*
* \remark: this functiion only apply in tranfer SPI mode
*/
MXD_RETURN_CODE MXD_EXPORT MXD_BurstRead (
	MXD_HANDLE hDevice,
	MXD_UINT8 burstMode,
	MXD_UINT8 bufferAddr,
	MXD_UINT32 burstLen,
	MXD_UINT8 *pBurstDataIn )
{
	MIRA_DEVICE_HANDLE* pDevice = (MIRA_DEVICE_HANDLE*) hDevice;
	MXD_RETURN_CODE eRtnCode = MXD_GENERAL_ERROR;
	MXD_UINT32 i;

	switch( pDevice->tDeviceConfig.eDataPath )
	{
	case MXD_I2C:
		for(i=0;i<burstLen;i++)
		{
			eRtnCode = MxdPorting_I2C_Read( pDevice->nDemodChipIndex, pDevice->tDeviceConfig.nI2cSlaveAddress, bufferAddr, pBurstDataIn+i );
			if( MXD_RTN_OK != eRtnCode )
			{
				return MXD_GENERAL_ERROR;
			}
		}
		break;
	case MXD_SPI:
		for(i=0;i<burstLen/SPI_BURST_LEN;i++)
		{
			eRtnCode = DDS_SpiCmd53( hDevice, SPI_READ_FLAG, burstMode, bufferAddr, SPI_BURST_LEN, pBurstDataIn+i*SPI_BURST_LEN);

			if( MXD_RTN_OK != eRtnCode )

			{
				return MXD_GENERAL_ERROR;
			}
		}
		eRtnCode = DDS_SpiCmd53( hDevice, SPI_READ_FLAG, burstMode, bufferAddr, (burstLen%SPI_BURST_LEN),pBurstDataIn+i*SPI_BURST_LEN ); 
		break;
	case MXD_TS:
		switch( pDevice->tDeviceConfig.eControlPath )
		{
		case MXD_I2C:
			for(i=0;i<burstLen;i++)
			{
				eRtnCode = MxdPorting_I2C_Read( pDevice->nDemodChipIndex, pDevice->tDeviceConfig.nI2cSlaveAddress, bufferAddr, pBurstDataIn+i );
				if( MXD_RTN_OK != eRtnCode )
				{
					return MXD_GENERAL_ERROR;
				}
			}
			break;
		case MXD_SPI:
			for(i=0;i<burstLen/SPI_BURST_LEN;i++)
			{
				eRtnCode = DDS_SpiCmd53( hDevice, SPI_READ_FLAG, burstMode, bufferAddr, SPI_BURST_LEN, pBurstDataIn+i*SPI_BURST_LEN);

				if( MXD_RTN_OK != eRtnCode )

				{
					return MXD_GENERAL_ERROR;
				}
			}
		default:
			return MXD_GENERAL_ERROR;
		}
		break;
	default:
		return MXD_GENERAL_ERROR;
	}
	return eRtnCode;
}/* end of MXD_BurstRead( ) */

MXD_RETURN_CODE DCC_WriteAntennaDac( MXD_HANDLE hDevice, MXD_UINT32 nFreq  );
/*!
* \par Description
* This function is used to tune freq. this function will return after pll is locked.
*
* \param hDevice	[IN] the handle of chip device which host is operating;
* \param nFreqKhz	[IN] the freqency to tune, unit is khz
*
* \return   
*    MXD_RTN_OK	-	the call succeeded
*
* \warning      
*/
MXD_RETURN_CODE MXD_EXPORT DCC_TuneFrequency( MXD_HANDLE hDevice, MXD_UINT32 nFreqKhz )
{
	MXD_RETURN_CODE eRtnCode = MXD_GENERAL_ERROR;	
	MIRA_DEVICE_HANDLE* pDevice = (MIRA_DEVICE_HANDLE*) hDevice;

	DCC_WriteAntennaDac( hDevice, nFreqKhz );
	g_CurrentFreq = nFreqKhz*1000;
	g_GubaoState = 0;
	eRtnCode = DCC_SetTunerFreq( hDevice, nFreqKhz*1000 );
	if( MXD_RTN_OK != eRtnCode )
	{
		MXD_DebugPrint( "DCC_TuneFrequency::Error:Set Tuner Freq error!\n" );
		return eRtnCode;		
	}

	eRtnCode = DCC_GetTunerStatus( hDevice );
	if( MXD_RTN_OK != eRtnCode )
	{
		MXD_DebugPrint( "DCC_TuneFrequency::Error:Tuner unlock!\n" );
		return eRtnCode;
	}
#ifndef SDK_NORMAL_MODE
	if((nFreqKhz/1000-498)%40 == 0)
	{
		pDevice->bSpurExist = TRUE;
	}
	else
	{
		pDevice->bSpurExist = FALSE;
	}
#endif
	DCC_UpdatePga(hDevice);
	MXD_DebugPrint( "DCC_TuneFrequency::OK!\n" );
	return eRtnCode;
}

/*********Demod Chip Controller Layer defines************************************************/

/*!
* \par Description
* This function is used to reset device.
*
* \param hDevice	[IN] the handle of chip device which host is operating;
*
* \return   
*    MXD_RTN_OK	-	the call succeeded
*
* \warning    
*/

MXD_RETURN_CODE DCC_ResetDevice( MXD_HANDLE hDevice )
{
	MIRA_DEVICE_HANDLE* pDevice = (MIRA_DEVICE_HANDLE*) hDevice;

	/* soft reset all modules */
	MXD_WriteRegFields( hDevice, REG_MISC_CFG, 0x3,1, 0);//Disable PGA       
	DCC_GetTickCount( hDevice );
	MXD_EX_WriteReg( hDevice, REG_SOFT_RST, 0X0 ); 
	pDevice->nTickSaved = 0;
	MXD_EX_WriteReg( hDevice, REG_SOFT_RST, 0XFF );
	MXD_WriteRegFields( hDevice, REG_MISC_CFG, 0x3,1, 1);//Enable PGA  
	/* clear all interrupt */
	MXD_EX_WriteReg( hDevice, REG_HIC1_INT_CLEAR, 0xff );
	MXD_EX_WriteReg( hDevice, REG_HIC2_INT_CLEAR, 0xff );
	MXD_EX_WriteReg( hDevice, REG_OTDD_INT_CLEAR, 0xff );
	MXD_EX_WriteReg( hDevice, REG_MISC_INT_CLEAR, 0xff );

	MXD_DebugPrint( "DCC_ResetDevice:: Reset device ok!\n" );
	return MXD_RTN_OK;
}


/*!
* \par Description
* This function is used to init device.
*
* \param hDevice	[IN] the handle of chip device which host is operating;
*
* \return   
*    MXD_RTN_OK	-	the call succeeded
*
* \warning    
*/

MXD_RETURN_CODE DCC_InitDevice( MXD_HANDLE hDevice )
{
	MIRA_DEVICE_HANDLE* pDevice = (MIRA_DEVICE_HANDLE*) hDevice;


	MXD_WriteRegFields(pDevice, REG_CTRL, 0x0, 5, 0x7d);// sfo & rs enable&ifo bypass
	MXD_WriteRegFields(pDevice, REG_CTRL, 0x6, 1, 0x1); // set ts full mode   byliujun
	MXD_WriteRegFields(pDevice, REG_CTRL, 7, 1, 0);
	MXD_WriteRegFields(pDevice, REG_CTRL, 5, 1, 0);//invert q

	/* Init dagc */
	MXD_EX_WriteReg(pDevice, REG_DAGC_ACC_NUM, 0x10);
	MXD_EX_WriteReg(pDevice, REG_DAGC_BR_VAL, 0X5f);
	MXD_EX_WriteReg(pDevice, REG_AGC_IQREF_L, 0x3e);
	MXD_EX_WriteReg(pDevice, REG_DAGC_FTS_CTRL, 0x6b); // dagc enable

	MXD_EX_WriteReg(pDevice, REG_OCU_SLICE_MODE_CFG, 0x05);   // set to default value;
	MXD_WriteRegFields(pDevice, REG_SC_VALID_CFG, 0x5, 1, 1);
	//

	/*open service QBL*/
	//MXD_EX_WriteReg(pDevice, REG_SC_INFO_C, 0x0);
	MXD_WriteRegFields(pDevice, REG_SC_INFO_C, 0x3, 3, 0x0);

	MXD_EX_WriteReg(pDevice, REG_SC5_CONFIG_A, 0x01);    //sc5 mem bloc num
	MXD_EX_WriteReg(pDevice, REG_SC5_CONFIG_B, 0x16);    //sc5 mem start blo1c

	MXD_EX_WriteReg(pDevice, REG_SC5_BGN_SLOT, 0);
	MXD_EX_WriteReg(pDevice, REG_SC5_NUM, 1);

	MXD_EX_WriteReg(pDevice, REG_SC4_SC5_THR, 0x01);

	MXD_WriteRegFields(pDevice, REG_LDPC_CONFIG, 0, 1, 0x1);

	//  MXD_EX_WriteReg(pDevice, REG_LDPC_STA_SIZE, 0x01);

	MXD_EX_WriteReg(pDevice, REG_OTDD_MISC_CTRL, 0x07);

	MXD_EX_WriteReg(pDevice, REG_MISC_CTRL, 0xfe); //enable clock gating;

	MXD_EX_WriteReg(pDevice, REG_LDPC_ITER_NUM_2QAM, 0x13);
	MXD_EX_WriteReg(pDevice, REG_LDPC_ITER_NUM_4QAM, 0x13);
	MXD_EX_WriteReg(pDevice, REG_LDPC_ITER_NUM_16QAM, 0x0e); //modified by liuyang



	MXD_EX_WriteReg(pDevice, REG_FTS_CHE_SWITCH_TIME_CFG, 0x12);  //
	MXD_EX_WriteReg(pDevice, REG_FTS_PRE_NUM, 0X0A);

	MXD_EX_WriteReg(pDevice, REG_AUTOSCALE_BW_CONFIG, 0XB); //step
	MXD_EX_WriteReg(pDevice, REG_AUTOSCALE_CONFIG, 0Xd3);
	MXD_EX_WriteReg(pDevice, REG_AUTOSCALE_REFBITWIDTH_FW_H, 0x14);
	MXD_EX_WriteReg(pDevice, REG_AUTOSCALE_REFBITWIDTH_FW_L, 0x00);
	MXD_EX_WriteReg(pDevice, REG_AUTOSCALE_PRECISION, 0X01);

	MXD_EX_WriteReg(pDevice, REG_SFO_TRACK_CFG, 0x0);  //all ts track mode

	MXD_EX_WriteReg(pDevice, REG_IFO2_WINDOW_WIDTH, 0x32);

	MXD_EX_WriteReg(pDevice, REG_CHE_CFG, 0x0);  //auto mode
	MXD_EX_WriteReg(pDevice, REG_AGC_INIT_DB, 0x2a);

	MXD_EX_WriteReg(pDevice, REG_ADC_TEST_PINS, 0x0);  //IQ reverse,by liujun

	MXD_EX_WriteReg(pDevice, REG_ADC_MODE_CTRL, 0x1e);  //2v adc
	MXD_EX_WriteReg(pDevice, REG_RF_MISC, RF_GAIN_DISABLE);
	if (NULL != pDevice->ActiveService[5].pRawFrameBuffer)
	{
		pDevice->ActiveService[5].nActiveServiceID = 0xffff;
	}
	else
	{
		pDevice->ActiveService[5].pRawFrameBuffer = MXD_Malloc( 8640*2 ); //for CLCH
		pDevice->ActiveService[5].nFrameBufLen = 8640;
		pDevice->ActiveService[5].nBufferLen = 8640*2;
		pDevice->ActiveService[5].nActiveServiceID = 0xffff;
	}
	MXD_DebugPrint( "DCC_InitDevice:: Init device ok!\n" );
	return MXD_RTN_OK;
}

/*!
* \par Description
* This function is used to make chip to sync the signal.
*
* \param hDevice	[IN] the handle of chip device which host is operating;
*
* \return   
*    MXD_RTN_OK	-	the call succeeded
*
* \warning    
*/

MXD_RETURN_CODE DCC_SyncSignal( MXD_HANDLE hDevice )
{
	MIRA_DEVICE_HANDLE* pDevice = (MIRA_DEVICE_HANDLE*) hDevice;
	MXD_RETURN_CODE eRtnCode = MXD_RTN_OK;
	MXD_UINT32 time;
	MXD_UINT8 i=0;

	DCC_ProcessGubao(hDevice);
	time = DCC_GetTickCount( hDevice );
	for(i=0;i<3;i++)
	{
		eRtnCode = DCC_DetectFo( hDevice );
		if( eRtnCode!= MXD_RTN_OK )
		{
			/* Detect STC */
			if(pDevice->ServiceSearchParam.nStcNum>=2)
			{
				pDevice->ServiceSearchParam.nStcNum = 0;
				return MXD_GENERAL_ERROR;
			}
			DCC_DetectStc( pDevice );
			eRtnCode = DCC_IsStcExist( hDevice );
			if( MXD_RTN_OK == eRtnCode )
			{
				pDevice->ServiceSearchParam.bStcStatus = FALSE;
				DCC_RemoveStc( pDevice );
				pDevice->ServiceSearchParam.nStcNum++;
			}
			else
			{
				pDevice->ServiceSearchParam.bStcStatus = TRUE;
				pDevice->ServiceSearchParam.nStcNum = 0;   
				return MXD_GENERAL_ERROR;
			}
		}
		else
		{
			MXD_DebugPrint( "Detect fo time is : %d!\n", DCC_GetTickCount( hDevice ) - time );
			DCC_ResetDevice( hDevice );
			DCC_InitDevice( hDevice );
#ifdef FIELDTEST_UPDATEREG
			FieldTestReadReg( hDevice, 2 );
			//	FieldTestUpdateReg();
#endif

			MXD_WriteRegFields( hDevice, REG_CTRL, 7, 1, 1 );
			MXD_EX_WriteReg( hDevice, REG_NCO_INIT_FREQ_OFT_L, (MXD_UINT8)(pDevice->foVal));
			MXD_EX_WriteReg( hDevice, REG_NCO_INIT_FREQ_OFT_M, (MXD_UINT8)(pDevice->foVal>>8));
			MXD_EX_WriteReg( hDevice, REG_NCO_INIT_FREQ_OFT_H, (MXD_UINT8)(pDevice->foVal>>16));

			/* CTS Init */
			MXD_EX_WriteReg( hDevice, REG_INIT, 0x1 ); 

			pDevice->ServiceSearchParam.nRefTick = 0;
			pDevice->bBigDelayStatus = FALSE;
			pDevice->bRecoveryStatus = FALSE;
			return MXD_RTN_OK;
		}
	}
	return MXD_GENERAL_ERROR;
}

/*!
* \par Description
* This function is used to check sync status.
*
* \param hDevice	[IN] the handle of chip device which host is operating;
*
* \return   
*    MXD_RTN_OK	-	the call succeeded
*
* \warning    
*/

MXD_RETURN_CODE DCC_IsSignalLocked( MXD_HANDLE hDevice )
{
	MIRA_DEVICE_HANDLE* pDevice = (MIRA_DEVICE_HANDLE*) hDevice;
	MXD_UINT8 syncStatus;
	MXD_UINT8 inrStatus;
	MXD_UINT8 crcStatus =0;
	static MXD_UINT32 nTimes = 0;

	MXD_EX_ReadReg( hDevice, REG_CLP_STATUS, &syncStatus );
#ifdef FIELDTEST_UPDATEREG
	if( (DCC_GetTickCount( hDevice ) - pDevice->ServiceSearchParam.nRefTick) % 1000 < 50  )
		FieldTestReadReg( hDevice, 2 );
#endif
	if( 0 != syncStatus )
	{
#ifdef FIELDTEST_UPDATEREG
		FieldTestReadReg( hDevice, 2 );
#endif

		//MXD_EX_WriteReg(hDevice,REG_RF_MISC, 0x1D);

		if( REG_AGC_LOCK_BIT != (syncStatus&REG_AGC_LOCK_BIT) )
		{
			MXD_DebugPrint( "DCC_IsSignalLocked:: agc lock fail!\n" );               
		}
		if( REG_CTS_FAIL_BIT == (syncStatus&REG_CTS_FAIL_BIT) )
		{
			MXD_DebugPrint( "DCC_IsSignalLocked:: cts fail!\n" );
			return MXD_CTS_FAIL;
		}
		if( REG_CTS_PASS_BIT == (syncStatus&REG_CTS_PASS_BIT) )
		{
			MXD_EX_ReadReg( hDevice, REG_MISC_INT_STATUS, &inrStatus );
			if( REG_TDP_IR_FTS_FAIL_IN_INIT_BIT == (inrStatus&REG_TDP_IR_FTS_FAIL_IN_INIT_BIT) )
			{
				MXD_EX_WriteReg( hDevice, REG_MISC_INT_CLEAR, REG_TDP_IR_FTS_FAIL_IN_INIT_CLEAR_BIT );
				MXD_DebugPrint( "DCC_IsSignalLocked:: cts detection error!  int status:0x%x!, sync status:0x%x!\n" , inrStatus, syncStatus );            
				return MXD_FTS_FAIL_INT;               
			}

			if( REG_FTS_FAIL_BIT == (syncStatus&REG_FTS_FAIL_BIT) )
			{
				MXD_UINT8 regVal1,regVal2;
				MXD_EX_WriteReg( hDevice, 0x3b,0xff);
				MXD_EX_ReadReg( hDevice, 0xb8,&regVal2);
				MXD_EX_ReadReg( hDevice, 0xd4,&regVal1);

				MXD_DebugPrint( "DCC_IsSignalLocked:: fts fail!  sync status:0x%x, ifol:0x%x, ifo2:0x%x\n" , syncStatus,regVal1,regVal2 );            
				return MXD_FTS_FAIL_CURRENT;
			}
			if( REG_FTS_PASS_BIT == (syncStatus&REG_FTS_PASS_BIT) )
			{
				if( pDevice->ServiceSearchParam.nRefTick != 0 ) 
				{                
					MXD_UINT8 dataStatus;

					MXD_EX_ReadReg( hDevice, REG_HIC1_INT_STATUS, &dataStatus );

					if( REG_HIC_IR_SC5_DAT_RDY_STATUS_BIT == (dataStatus&REG_HIC_IR_SC5_DAT_RDY_STATUS_BIT) )
					{
						MXD_WriteRegFields( hDevice, REG_HIC1_INT_CLEAR, 5, 1, 1 );

						MXD_EX_ReadReg( hDevice, REG_MISC_INT_STATUS, &crcStatus );
						if( REG_OTDD_IR_CRC_ERR_STATUS_BIT == (crcStatus&REG_OTDD_IR_CRC_ERR_STATUS_BIT) )
						{
							MXD_WriteRegFields( hDevice, REG_MISC_INT_CLEAR, 1, 1, 1 ); 
							if (nTimes != DCC_GetTickCount( hDevice ))
							{
								MXD_DebugPrint( "DCC_IsSignalLocked:: Signal Lokced,CLCH crc failed at %d! sync status:0x%x,misc status:0x%x\n" ,DCC_GetTickCount( hDevice ), syncStatus,crcStatus ); 
								nTimes = DCC_GetTickCount( hDevice );
							}
							return MXD_CLCHCRC_FAIL;
						} 
						else
						{   
							MXD_WriteRegFields( hDevice, REG_CTRL, 7, 1, 0 );
							if (nTimes != DCC_GetTickCount( hDevice ))
							{
								MXD_DebugPrint( "DCC_IsSignalLocked:: Signal Locked,CLCH crc pass at %d,cost time is:%d! sync status:0x%x,misc status:0x%x\n" ,DCC_GetTickCount( hDevice ),DCC_GetTickCount( hDevice ) - pDevice->ServiceSearchParam.nRefTick,syncStatus,crcStatus );  
								nTimes = DCC_GetTickCount( hDevice );
							}
							//MXD_EX_WriteReg( hDevice, REG_RF_MISC, RF_GAIN_DISABLE );
							return MXD_RTN_OK;
						}

					}
					else
					{
						if( (DCC_GetTickCount( hDevice ) - pDevice->ServiceSearchParam.nRefTick) % 1000 < 50  )
						{
							//                       MXD_EX_ReadReg( hDevice, REG_MISC_INT_STATUS, &crcStatus );
							//                       MXD_DebugPrint( "DCC_IsSignalLocked::_______________crc status 0x%x!____________\n", crcStatus );

							if (nTimes != DCC_GetTickCount( hDevice ))
							{
								MXD_DebugPrint( "DCC_IsSignalLocked:: sync status:0x%x,misc status:0x%x,data status,0x%x, waiting data ready status... at %d!\n" ,syncStatus,crcStatus,dataStatus, DCC_GetTickCount( hDevice ) );
								nTimes = DCC_GetTickCount( hDevice );
							}
						}
						if( (DCC_GetTickCount( hDevice ) - pDevice->ServiceSearchParam.nRefTick) > 10000 )
						{
							if (nTimes != DCC_GetTickCount( hDevice ))
							{
								MXD_DebugPrint( "DCC_IsSignalLocked:: sync status:0x%x,misc status:0x%x,data status,0x%x, waiting data ready timeout at %d!\n" ,syncStatus,crcStatus,dataStatus, DCC_GetTickCount( hDevice ) );
								nTimes = DCC_GetTickCount( hDevice );
							}
							return MXD_TIME_OUT;
						}
						return MXD_POLLING_STATUS;
					}
				}
				else
				{
					pDevice->ServiceSearchParam.nRefTick = DCC_GetTickCount( hDevice );
					return MXD_POLLING_STATUS;
				}
			}
			else
			{
				if( pDevice->ServiceSearchParam.nRefTick != 0 ) 
				{                
					if( (DCC_GetTickCount( hDevice ) - pDevice->ServiceSearchParam.nRefTick) > 250 )
					{
						MXD_DebugPrint( "DCC_IsSignalLocked:: sync status:0x%x,ifo1 hold timeout at %d!\n" ,syncStatus,DCC_GetTickCount( hDevice ) );
						return MXD_TIME_OUT;
					}
					return MXD_POLLING_STATUS;

				}
				else
				{
					pDevice->ServiceSearchParam.nRefTick = DCC_GetTickCount( hDevice );
					return MXD_POLLING_STATUS;
				}				
			}
		}
	}
	return MXD_POLLING_STATUS;
}

/*!
* \par Description
* This function is used to set sfo and lpc mode when tracking.
*
* \param hDevice	[IN] the handle of chip device which host is operating;
*
* \return   
*    MXD_RTN_OK	-	the call succeeded
*
* \warning    
*/

MXD_RETURN_CODE DCC_SetTrackMode( MXD_HANDLE hDevice )
{
	MIRA_DEVICE_HANDLE* pDevice = (MIRA_DEVICE_HANDLE*) hDevice;
	MXD_UINT8 regVal;
	MXD_UINT8 sfoValH,sfoValM,sfoValL;
	MXD_INT32 sfoFrzVal;
	MXD_ReadRegFields(pDevice, REG_HIC2_INT_STATUS, 0x07, 1, &regVal);

	MXD_EX_WriteReg(pDevice, REG_SFO_TRACK_CFG, 0x0);  //all ts track mode

	MXD_WriteRegFields(pDevice, REG_FREEZE_CTRL, 0x03, 1, 1); //freeze sfo value
	MXD_EX_ReadReg(pDevice, REG_SFO_FRZ_VAL_H, &sfoValH);
	MXD_EX_ReadReg(pDevice, REG_SFO_FRZ_VAL_M, &sfoValM);
	MXD_EX_ReadReg(pDevice, REG_SFO_FRZ_VAL_L, &sfoValL);
	if(sfoValH&0x08)
	{
		sfoFrzVal = (MXD_INT32)((MXD_UINT32)(sfoValH<<16)+(MXD_UINT16)(sfoValM<<8) + sfoValL - 16777216 );
	}
	else
	{
		sfoFrzVal = (MXD_INT32)((MXD_UINT32)(sfoValH<<16)+(MXD_UINT16)(sfoValM<<8) + sfoValL );
	}
	sfoFrzVal = sfoFrzVal*40/200;
	MXD_DebugPrint( "DCC_SetTrackMode::Current sfo is %d Hz!\n", sfoFrzVal );

	return MXD_RTN_OK;
}

MXD_RETURN_CODE DCC_DetectCheMode( MXD_HANDLE hDevice )
{
	MIRA_DEVICE_HANDLE* pDevice = (MIRA_DEVICE_HANDLE*) hDevice;
	MXD_UINT8 maxDelayH;
	MXD_UINT8 maxDelayL;
	MXD_UINT8 secondPathH;
	MXD_UINT8 secondPathL;
	MXD_UINT16 maxDelayVal;
	MXD_UINT16 secondPathVal;

	//  MXD_RETURN_CODE eRtnCode = MXD_RTN_OK;

	MXD_EX_WriteReg(pDevice, REG_FREEZE_CTRL, 0xff);
	MXD_EX_ReadReg(pDevice, REG_FTS_MAX_DELAY_SPREAD_H, &maxDelayH);
	MXD_EX_ReadReg(pDevice, REG_FTS_MAX_DELAY_SPREAD_L, &maxDelayL);
	maxDelayVal = (MXD_UINT16)(maxDelayH<<8) + maxDelayL;
	MXD_EX_ReadReg(pDevice, REG_FTS_SECONDARY_PATH_H, &secondPathH);
	MXD_EX_ReadReg(pDevice, REG_FTS_SECONDARY_PATH_L, &secondPathL);
	secondPathVal = (MXD_UINT16)(secondPathH<<8) + secondPathL;
	if( (maxDelayVal>512)&&(secondPathVal<80))
	{
		MXD_DebugPrint( "DCC_DetectCheMode:: max delay is %d, second path is %d!\n",maxDelayVal,secondPathVal);
		MXD_EX_WriteReg(pDevice, REG_CHE_CFG, 0x2);  //manual mode
		pDevice->bBigDelayStatus = TRUE;
	}
	else
	{
		MXD_EX_WriteReg(pDevice, REG_CHE_CFG, 0x0);  //auto mode
		pDevice->bBigDelayStatus = FALSE;
	}   
	return MXD_RTN_OK;
}

MXD_RETURN_CODE DCC_DetectFo( MXD_HANDLE hDevice )
{
	MIRA_DEVICE_HANDLE* pDevice = (MIRA_DEVICE_HANDLE*) hDevice;
	MXD_UINT8 regVal; 
	MXD_UINT8 ifo2Val,ffoL,ffoH;
	MXD_BOOL bAgcLock = FALSE;
	MXD_UINT32 tick;
	MXD_INT32 ifo2,ffo;

	DCC_InitDevice(pDevice);

	DCC_ResetDevice(pDevice);

	MXD_EX_WriteReg(pDevice, REG_AGC_CFG, 0x5);
	MXD_EX_WriteReg(pDevice, REG_INIT, 1);
	tick = DCC_GetTickCount(pDevice);
	while (DCC_GetTickCount(pDevice) - tick < 2000)
	{
		MXD_EX_ReadReg(pDevice, REG_CLP_STATUS, &regVal);
		if( 0x04 == (regVal&0x04) )
		{
			bAgcLock = TRUE;

			pDevice->foVal = 0;
			MXD_EX_WriteReg(pDevice, REG_FREEZE_CTRL, 0x02);
			MXD_EX_ReadReg(pDevice, REG_NCO_FRZ_IFO2_VAL , &ifo2Val);
			MXD_EX_ReadReg(pDevice, REG_NCO_FRZ_FFO_RFO_L, &ffoL);
			MXD_EX_ReadReg(pDevice, REG_NCO_FRZ_FFO_RFO_H, &ffoH);
			if(ifo2Val&0x80)
			{
				ifo2 = ifo2Val - 256;
			}
			else
			{
				ifo2 = ifo2Val;
			}

			if( ffoH&0x10 )
			{
				ffo = (MXD_INT32)(ffoH<<8) + ffoL - 8192;
			}
			else
			{
				ffo = (MXD_INT32)(ffoH<<8) + ffoL;
			}

			pDevice->foVal = -( ifo2*2048 - ffo - g_AddFoHz*32768/78125 );

			MXD_DebugPrint("DCC_DetectFo::freq offset is :%d, add fo is: %dHz!\n", ifo2*2048 - ffo, g_AddFoHz);

			return MXD_RTN_OK;
		}
		else if( (0x08 == (regVal&0x08))||(0x02 == (regVal&0x02)))
		{
			MXD_DebugPrint("DCC_DetectFo::cts or fts failed, sync status: 0x%x!\n", regVal);
			//bAgcLock = TRUE;
			break;     
		}
	}
	return MXD_GENERAL_ERROR;
}
/*!
* \par Description
* This function is used to detect single tone.
*
* \param hDevice	[IN] the handle of chip device which host is operating;
*
* \return   
*    MXD_RTN_OK	-	the call succeeded
*
* \warning    
*/

MXD_RETURN_CODE DCC_DetectStc( MXD_HANDLE hDevice )
{
	MIRA_DEVICE_HANDLE* pDevice = (MIRA_DEVICE_HANDLE*) hDevice;
	DCC_ResetDevice( hDevice );
	MXD_WriteRegFields( hDevice, REG_MISC_INT_CLEAR, 0x06,1, 1);//clear stc done interrupt
	MXD_EX_WriteReg( hDevice, REG_STC_SHT_CFG, 0x03 );
	MXD_EX_WriteReg( hDevice, REG_STC_PARA, 0x3f );   //?
	MXD_EX_WriteReg( hDevice, REG_STC_ST_THR, 0x3f );
	MXD_WriteRegFields( hDevice, REG_MISC_INT_CLEAR, 0x06,1, 1);//clear stc done interrupt  
	MXD_EX_WriteReg( hDevice, REG_DAGC_FTS_CTRL, 0x7b );//dagc disable
	if( 1 == pDevice->ServiceSearchParam.nStcNum )
	{
		MXD_EX_WriteReg( hDevice, REG_NCO_INIT_FREQ_OFT_H, 0x0);
	}
	MXD_WriteRegFields( hDevice, REG_INIT, 0x1, 1, 1 );//init STC 
	MXD_DebugPrint("DCC_DetectStc::Begin to stc detect!\n");
	return MXD_RTN_OK;
}

/*!
* \par Description
* This function is used to judge single tone.
*
* \param hDevice	[IN] the handle of chip device which host is operating;
*
* \return   
*    MXD_RTN_OK	-	the call succeeded
*
* \warning    
*/

MXD_RETURN_CODE DCC_IsStcExist( MXD_HANDLE hDevice )
{
	MIRA_DEVICE_HANDLE* pDevice = (MIRA_DEVICE_HANDLE*) hDevice;
	MXD_UINT8 regVal; 
	MXD_UINT8 stcIdxH;
	MXD_UINT8 stcIdxL;
	MXD_UINT16 stcRealStr;
	MXD_UINT16 stcRealWid;
	MXD_INT32 stcRealPos;
	MXD_UINT32 stcRefThld;
	MXD_UINT32 i;
	MXD_UINT32 tick = DCC_GetTickCount(pDevice);
	while (DCC_GetTickCount(pDevice) - tick < 2000)
	{
		MXD_EX_ReadReg(pDevice, REG_MISC_INT_STATUS, &regVal);
		if(REG_FDP_IR_STC_DONE_STATUS_BIT == (regVal&REG_FDP_IR_STC_DONE_STATUS_BIT))
		{
			MXD_EX_ReadReg(pDevice, REG_STC_ST_IDX_H, &stcIdxH);
			MXD_EX_ReadReg(pDevice, REG_STC_ST_IDX_L, &stcIdxL);
			pDevice->ServiceSearchParam.nStcRealIdx[pDevice->ServiceSearchParam.nStcNum]  = (MXD_UINT16)(stcIdxH<<8) + stcIdxL;
			MXD_EX_ReadReg(pDevice, REG_STC_ST_STR, &regVal);
			stcRealStr = regVal<<6;
			MXD_EX_ReadReg(pDevice, REG_STC_ST_WID, &regVal);
			stcRealWid = regVal<<1;  
			MXD_EX_WriteReg(pDevice, REG_STC_ST_THR, 0x0);
			stcRealPos = pDevice->ServiceSearchParam.nStcRealIdx[pDevice->ServiceSearchParam.nStcNum]*78125/32;
			if( stcRealPos > 5000000 )
			{
				stcRealPos -= 10000000;
			}

			if( ((stcRealPos>=3500000)&&(stcRealPos<=4000000))||((stcRealPos>=-4000000)&&(stcRealPos<=-3500000)))
			{
				stcRefThld = 500;   
			}
			else
			{
				stcRefThld = 1000;
			}
			if( stcRealStr> stcRefThld )
			{
				MXD_DebugPrint("DCC_IsStcExist::stc is exist! strength is:%d, index is:%d\n",stcRealStr,pDevice->ServiceSearchParam.nStcRealIdx[pDevice->ServiceSearchParam.nStcNum] );
				return MXD_RTN_OK;
			}
			else
			{
				MXD_DebugPrint("DCC_IsStcExist::stc is not exist! strength is:%d, index is:%d\n",stcRealStr,pDevice->ServiceSearchParam.nStcRealIdx[pDevice->ServiceSearchParam.nStcNum] );
				break;
			}            
		}
	}

	return MXD_GENERAL_ERROR;
}

/*!
* \par Description
* This function is used to remove single tone.
*
* \param hDevice	[IN] the handle of chip device which host is operating;
*
* \return   
*    MXD_RTN_OK	-	the call succeeded
*
* \warning    
*/

MXD_RETURN_CODE DCC_RemoveStc( MXD_HANDLE hDevice )
{
	MIRA_DEVICE_HANDLE* pDevice = (MIRA_DEVICE_HANDLE*) hDevice;
	if( 0 == pDevice->ServiceSearchParam.nStcNum )
	{
		MXD_DebugPrint("DCC_RemoveStc::open 1st notch!\n");
		MXD_WriteRegFields( hDevice, REG_STC_CFIG_IDX_H, 0x0,4,(MXD_UINT8)(pDevice->ServiceSearchParam.nStcRealIdx[0]>>8) );       
		MXD_EX_WriteReg( hDevice, REG_STC0_CFIG_IDX_L, (MXD_UINT8)(pDevice->ServiceSearchParam.nStcRealIdx[0]));
		MXD_WriteRegFields( hDevice, REG_STC_MISC_CTRL, 0x04, 3 ,0x02 );//config notch width
		MXD_WriteRegFields( hDevice, REG_STC_MISC_CTRL, 0x07, 1 ,1 );//enable 1st notch filter

	}
	else if( 1 == pDevice->ServiceSearchParam.nStcNum)
	{
		MXD_DebugPrint("DCC_RemoveStc::open 2nd notch!\n");
		MXD_WriteRegFields( hDevice, REG_STC_CFIG_IDX_H, 0x4,4,(MXD_UINT8)(pDevice->ServiceSearchParam.nStcRealIdx[1]>>8) );  
		MXD_EX_WriteReg( hDevice, REG_STC1_CFIG_IDX_L, (MXD_UINT8)(pDevice->ServiceSearchParam.nStcRealIdx[1]));
		MXD_WriteRegFields( hDevice, REG_STC_MISC_CTRL, 0x00, 3 ,0x02 );//config notch width   
		MXD_WriteRegFields( hDevice, REG_STC_MISC_CTRL, 0x03, 1 ,1 );//enable 2nd notch filter    

	}
	else
	{
		return MXD_GENERAL_ERROR;
	}
	return MXD_RTN_OK;
}

/*!
* \par Description
* This function is used to config viner coeff manually.
*
* \param hDevice	[IN] the handle of chip device which host is operating;
*
* \return   
*    MXD_RTN_OK	-	the call succeeded
*
* \warning    
*/
MXD_RETURN_CODE DCC_WriteCoeff( MXD_HANDLE hDevice )
{
	//  MIRA_DEVICE_HANDLE* pDevice = (MIRA_DEVICE_HANDLE*) hDevice;
	MXD_RETURN_CODE eRtnCode = MXD_RTN_OK;
	MXD_UINT8 i;
	MXD_UINT8 coeffArray[7][COEFF_ARRAY_LEN]={
		{243, 27 , 85 , 29 , 252, 34 , 20 , 224, 0  , 220, 15 , 255, 232, 155,
		68 , 21 , 220, 34 , 22 , 20 , 17 , 237, 123, 255, 224, 19 , 68 , 13  ,
		188, 34 , 22 , 72 , 17 , 253, 235, 255, 219, 139, 51 , 5  , 152, 34  ,
		22 , 124, 17 , 11 , 96 , 0  , 216, 3  , 51 , 254, 115, 34 , 20 ,  176,
		17 , 22 , 224, 0  , 216, 119, 34 , 248, 71 , 34 , 17 , 228, 17 , 31  ,
		100, 17 , 219, 239, 17 , 243, 23 , 34 , 13 , 20 , 34 , 37 , 236, 17  ,
		225, 103, 17 , 239, 231, 17 , 8  , 68 , 34 , 40 , 116, 34 , 234,  227,
		0  , 236, 179, 17 , 2  , 112, 34 , 40 , 0  , 51 , 245, 99 , 0  ,  234,
		127, 17 , 251, 155, 34 , 37 , 136, 51 , 3  , 232, 255, 234, 75 , 17  ,
		243, 191, 34 , 32 , 16 , 68 , 19 , 120, 255, 234, 23 , 17 , 235,  223,
		34 , 24 , 152, 68 ,}, 
		{ 240,  15 , 102, 74 , 236, 17 , 246,  239, 255,
		208, 31 , 0  , 200, 19 , 85 , 72 , 148, 34 , 35 , 92 , 0 , 205, 3  , 0
		, 175, 11, 68, 57, 36, 51, 70,  240,0 ,  210, 235, 255,165, 255, 34 , 32 ,
		140, 51 , 91 ,  156,17 ,  224, 223, 255,170, 11, 34, 0 ,188, 51, 97,  76 ,
		34 , 245, 239,255,187, 59 , 17 ,  221,183, 51 , 88 ,  240,34, 16 , 40,  0 ,
		212, 151, 0, 190,111, 51 , 66 ,  108, 51 , 44 ,148, 0,240, 43 , 0 , 168,
		243, 34 , 35 ,  180,51, 69 , 56, 17,11 , 236, 255,159,79 ,   34 ,   0,188,
		51, 86 , 8 ,  34  ,32 ,  220, 255,165,159, 17 ,  224,143,51 , 91 , 252, 34,
		46 ,  232, 255,186, 243, 0 , 199, 39 , 51, 81 , 8  , 68 , 51 ,0 , 0 , 221, 
		95 ,  0, 184, 151, 34 , 56 ,16 , 85 ,}, 
		{ 237, 155, 102, 80 , 240, 0  , 198, 83 , 0  , 253, 43 , 0
		, 159, 67 , 85  , 119, 60 , 34  , 251, 3  , 0   , 238, 135, 0  ,  123,
		163, 51 , 112, 144, 51 , 61 , 36 , 0  , 217, 175, 0  , 129, 23 , 34  ,
		63 , 144, 68 , 121, 192, 0  , 199, 155, 0  , 167, 231, 0  , 248,  255,
		68 , 158, 196, 17 , 195, 95 , 0  , 219, 55 , 0  , 175, 199, 68 ,  164,
		240, 34 , 210, 27 , 0  , 11 , 252, 255, 120, 7  , 68 , 136, 4  , 68  ,
		245, 255, 255, 46 , 24 , 0  , 92 , 243, 34 , 81 , 196, 68 , 37 , 52  ,
		0  , 61 , 92 , 0  , 98 , 199, 17 , 8  , 252, 68 , 89 , 228, 0  , 57  ,
		152, 0  , 135, 195, 0  , 193, 147, 68 , 127, 20 , 34 , 39 , 172, 0   ,
		195, 39 , 0  , 144, 147, 51 , 133, 160, 51 , 18 , 132, 0  , 5  , 0   ,
		0  , 137, 63 , 34 , 97 , 64 ,  85 ,}, 
		{ 234, 199, 102, 56 , 60 , 0   ,
		224, 11 , 17 , 254, 255, 255, 122, 63 , 85 , 180, 216, 17 , 205,  207,
		0  , 5  , 28 , 0  , 81 , 19 , 51 , 200, 52 , 68 , 223, 67 , 0  , 8   ,
		128, 0  , 118, 43 , 17 , 114, 248, 85 , 30 , 244, 255, 249, 235, 0   ,
		196, 39 , 0  , 236, 87 , 102, 114, 116, 0  , 222, 23 , 17 , 12 , 8   ,
		0  , 123, 83 , 85 , 176, 200, 17 , 201, 227, 0  , 51 , 108, 0  , 69  ,
		151, 51 , 187, 148, 51 , 205, 111, 0  , 55 , 224, 0  , 80 , 203, 17  ,
		133, 80 , 85 , 244, 11 , 0  , 34 , 20 , 17 , 142, 119, 0  , 20 , 84  ,
		102, 60 , 36 , 0  , 7  , 232, 0  , 226, 247, 255, 142, 251, 85 ,  138,
		40 , 17 , 248, 131, 0  , 33 , 64 , 0  , 56 , 55 , 68 , 175, 16 , 51  ,
		251, 31 , 0  , 51 , 204, 0  , 76 , 219, 17 , 134, 60 , 85 , }, 
		{  233,219, 102, 31 , 8 , 0  , 251, 35 , 17 , 254, 3 , 0  , 103, 51 , 85  ,
		204, 124, 17 , 214, 103, 17 , 248, 243, 255, 66 , 187, 34 , 248, 72  ,
		68 , 192, 235, 0  , 6  , 28 , 0  , 127, 187, 0  , 145, 128, 102,  227,
		43 , 0  , 13 , 160, 0  , 225, 255, 255, 233, 211, 102, 59 , 16 , 0   ,
		251, 43 , 17 , 40 , 72 , 0  , 102, 87 , 85 , 153, 24 , 17 , 217, 79  ,
		17 , 59 , 232, 0  , 60 , 27 , 51 , 196, 24 , 51 , 197, 235, 0  , 39  ,
		76 , 17 , 103, 27 , 17 , 154, 84 , 85 , 216, 75 , 0  , 5  , 40 , 17  ,
		197, 19 , 0  , 23 , 208, 102, 31 , 252, 255, 243, 163, 0  , 29 , 40  ,
		0  , 111, 131, 102, 129, 184, 0  , 250, 31 , 0  , 64 , 232, 0  , 8   ,
		75 , 68 , 190, 184, 34 , 8  , 240, 255, 42 , 100, 17 , 52 , 127, 17  ,
		153, 48 , 85 ,}, 
		{ 237, 139, 85 ,  97 , 100, 17 , 216, 27 , 0  ,  217,
		255, 0 , 142, 151, 51 , 96 , 100,  51 , 81 , 92 , 0  , 193, 179,  0  ,
		148, 99 , 17 , 254, 135, 68 , 152, 0  , 34 , 214, 35 , 0  , 225, 35  ,
		0  , 139, 227, 51 , 117, 224, 51 , 31 , 32 , 0  , 42 , 32 , 0  ,  104,
		3  , 34 , 2  , 132, 68 , 108, 96 , 17 , 63 , 176, 0  , 175, 95 , 0   ,
		160, 103, 51 , 114, 148, 51 , },
		{ 234, 151, 85, 67, 100, 0, 185, 119, 17, 27, 148, 0, 103, 239, 34, 150, 128,
		51, 3, 252, 255, 0, 152, 17, 186, 75, 0, 243, 99, 85, 153, 212, 0, 186, 131,
		17, 57, 80, 0, 82, 179, 51, 174, 176, 51, 199, 83, 0, 70, 128, 17, 103, 215,
		0, 13, 96, 85, 70, 72, 0, 0, 152, 17, 253, 255, 255, 106, 131, 51, 153, 236,
		34,}
	};

	for(i=0;i<7;i++)
	{
		MXD_EX_WriteReg( hDevice, REG_COEFF_IDX, i);
		eRtnCode = MXD_BurstWriteReg( hDevice, REG_COEFF_ADDR, coeffArray[i], COEFF_ARRAY_LEN );
		if( MXD_RTN_OK != eRtnCode )
		{
			return eRtnCode;
		}
		MXD_WriteRegFields( hDevice, REG_STORE_HN_CONTROL, 0x1,1,1);/*reset hn*/
	}
	MXD_WriteRegFields( hDevice, REG_FTS_COEF_CFG, 0x0,3,0);

	return eRtnCode;
}

/*!
* \par Description
* This function is used to get signal power.
*
* \param hDevice	[IN] the handle of chip device which host is operating;
*
* \return   
*    MXD_INT8	-	output scale [-100-0]
*
* \warning    
*/

MXD_INT8 DCC_GetSignalPwr( MXD_HANDLE hDevice )
{

	MIRA_DEVICE_HANDLE* pDevice = (MIRA_DEVICE_HANDLE*) hDevice;

	MXD_INT8 signalPwr = -70;
	MXD_INT8 lnaGain[] = {-3,0,4,12,16,20,0,0,0,0,0,0,13,8};//dB
	MXD_INT8 pgaGain = 0;
	MXD_INT8 mixerGain = 0;
	MXD_UINT8 lnaVal,pgaVal,mixerVal;
	MXD_UINT8 regVal;
	//lna gain
	//   MXD_EX_ReadTunerReg( pDevice, 0x2, &regVal );
	//if(regVal!=0)
	//	return signalPwr;

	MXD_EX_ReadTunerReg( pDevice, 0x77, &lnaVal );
	if( ( lnaVal==0 )||(lnaVal>0xe))
		lnaVal = 1;

	//pga gain
	MXD_EX_ReadTunerReg( pDevice, 0x79, &pgaVal );
	pgaGain = (pgaVal>>2) - 6;

	//mixer gain
	MXD_EX_ReadTunerReg( pDevice, 0x78, &mixerVal );
	switch(mixerVal&0x30)
	{
	case 0:
		mixerGain = (mixerVal&0x0f) + 6;
		break;
	case 0x10:
		mixerGain = (mixerVal&0x0f) + 12;
		break;
	case 0x20:
		mixerGain = (mixerVal&0x0f) + 18;
		break;
	case 0x30:
		mixerGain = (mixerVal&0x0f) + 21;
		break;
	default:
		break;
	}
	if((mixerGain<6)||(mixerGain>36))
		mixerGain = 10;

	signalPwr = -8 - lnaGain[lnaVal-1] - mixerGain - pgaGain;
	//MXD_DebugPrint( "DCC_GetSignalPwr::signalPwr:%d,0x77=0x%x, 0x78=0x%x, 0x79=0x%x!\n",signalPwr, lnaVal,mixerVal,pgaVal );
	return signalPwr;
}

/*!
* \par Description
* This function is used to get system RSSI.
*
* \param hDevice	[IN] the handle of chip device which host is operating;
*
* \return   
*    MXD_INT8	-	output scale [-100-0]
*
* \warning    
*/

MXD_INT8 DCC_GetSystemRssi( MXD_HANDLE hDevice )
{
	MIRA_DEVICE_HANDLE* pDevice = (MIRA_DEVICE_HANDLE*) hDevice;
	MXD_INT8 rssi = 0;

	rssi = DCC_GetSignalPwr( pDevice );
	return rssi;

}

/*!
* \par Description
* This function is used to get system SNR.
*
* \param hDevice	[IN] the handle of chip device which host is operating;
*
* \return   
*    MXD_UINT8	-	output scale [0-100]
*
* \warning    
*/

MXD_UINT8 DCC_GetSystemSnr( MXD_HANDLE hDevice , MXD_SYS_STATUS *sys_status )
{
	MIRA_DEVICE_HANDLE* pDevice = (MIRA_DEVICE_HANDLE*) hDevice;
	// MXD_DEMUXER_CONTEXT* pDemuxCtx = (MXD_DEMUXER_CONTEXT*)pDevice->pDemuxerPrivateStruct;

	MXD_INT8 snr = 0;
	MXD_INT8 signalPwr;
	MXD_UINT16 ldpcErr;
	MXD_UINT16 ldpcWindow;
	MXD_UINT8 maxIterNum[3]={19,19,15};
	MXD_UINT8 iterThld[3] = {9,9,9};
	MXD_UINT8 realIter;
	MXD_UINT8 curMode = 0;

	MXD_UINT8 maxCurMode = 0;
	MXD_UINT16 blerVal         = 0;

	signalPwr = DCC_GetSignalPwr( hDevice );
	sys_status->nSignalStrength = signalPwr;    
	if( !pDevice->bSystemLockStatus )
	{
		return 0;
	}

	DTP_GetBler( hDevice, &ldpcErr, &ldpcWindow );
	if( 0 != ldpcWindow)
	{
		blerVal = ldpcErr*100/ldpcWindow;	
		if(blerVal>=100)
		{
			blerVal = 100;
		}
	}

	MXD_EX_ReadReg( hDevice, REG_ITER_NUM, &realIter );
	if( (0 == ldpcWindow)||( 0 == realIter) )
	{
		return 0;
	}    
	if( (0 == ldpcErr) && ( realIter <= iterThld[maxCurMode] ) )
	{
		snr = SNR_ITER_THRD_FACTOR + (100-SNR_ITER_THRD_FACTOR)*(iterThld[maxCurMode]-realIter)/(iterThld[maxCurMode]-3);
	}
	else if( blerVal > BLER_THLD )
	{
		snr = (SNR_BLER_THRD_FACTOR-14)*(100-blerVal)/100 + (signalPwr+90)/6 ;
	}
	else if ((/*(blerVal>=0)&&*/(blerVal < BLER_THLD)) || ((realIter > iterThld[maxCurMode]) && (realIter <= maxIterNum[maxCurMode])))
	{
		snr = SNR_BLER_THRD_FACTOR + (SNR_ITER_THRD_FACTOR - SNR_BLER_THRD_FACTOR)*(maxIterNum[curMode]-realIter)/((maxIterNum[curMode]- iterThld[maxCurMode])*2)
			+ (SNR_ITER_THRD_FACTOR - SNR_BLER_THRD_FACTOR)*(BLER_THLD-blerVal)/(BLER_THLD*2) ;
	}
	if( snr > 100 )
	{
		snr = 100;
	}
	if( snr < 0 )
	{
		snr = 0;
	}
	sys_status->nLdpcErrPercent = ldpcErr;
	sys_status->nLdpcWindow = ldpcWindow;
	sys_status->nSignalStrength = signalPwr;
	return snr;
}

/*!
* \par Description
* This function is used to get system lock status.
*
* \param hDevice	[IN] the handle of chip device which host is operating;
*
* \return   
*    MXD_RTN_OK	-	the call succeeded
*
* \warning    
*/

MXD_RETURN_CODE DCC_GetSystemStatus( MXD_HANDLE hDevice )
{
	MIRA_DEVICE_HANDLE* pDevice = (MIRA_DEVICE_HANDLE*) hDevice;
	MXD_UINT8 regVal;
	MXD_UINT16 blerVal = 0;
	MXD_UINT16 blerWindow = 30;
	MXD_UINT16 bler = 0;
	MXD_UINT8 maxDelayH;
	MXD_UINT8 maxDelayL;
	MXD_UINT8 secondPathH;
	MXD_UINT8 secondPathL;
	MXD_UINT16 maxDelayVal;
	MXD_UINT16 secondPathVal;
	MXD_UINT8 cheCfg;

	MXD_RETURN_CODE eRtnCode = MXD_RTN_OK;
	if( !pDevice->bSystemLockStatus )
	{
		return MXD_SYSTEM_UNLOCK;
	}

	eRtnCode = MXD_EX_ReadReg( hDevice,  REG_HIC1_INT_STATUS ,&regVal );
	if( MXD_RTN_OK != eRtnCode )
	{
		MXD_DebugPrint( "DCC_GetSystemStatus:: Read Reg error!\n" );
		return eRtnCode;
	}
	if( REG_TDP_IR_SFO_UNLOCK_INT_BIT == (regVal&REG_TDP_IR_SFO_UNLOCK_INT_BIT) )
	{
		MXD_EX_WriteReg( hDevice,REG_HIC1_INT_CLEAR,REG_TDP_IR_SFO_UNLOCK_INT_CLEAR_BIT );
		MXD_DebugPrint( "DCC_GetSystemStatus:: SFO tracking unlock!\n" );
	}
	else if( REG_TDP_IR_FTS_FAIL_IN_NORMAL_BIT == (regVal&REG_TDP_IR_FTS_FAIL_IN_NORMAL_BIT))
	{
		MXD_EX_WriteReg( hDevice,REG_HIC1_INT_CLEAR,REG_TDP_IR_FTS_FAIL_IN_NORMAL_CLEAR_BIT );
		MXD_DebugPrint( "DCC_GetSystemStatus:: Fine timing track is Loss!\n" );	
		return MXD_SYSTEM_UNLOCK;
	}

	MXD_EX_WriteReg( hDevice, REG_FREEZE_CTRL, 0x05 );

	MXD_EX_ReadReg( hDevice, REG_CHE_CFG, &cheCfg );
	if( cheCfg == 0x02)
	{
		pDevice->bBigDelayStatus = TRUE;
	}
	else
	{
		pDevice->bBigDelayStatus = FALSE;
	}
	if( pDevice->bBigDelayStatus )
	{
		MXD_EX_ReadReg( hDevice,REG_FTS_MAX_DELAY_SPREAD_H, &maxDelayH );
		MXD_EX_ReadReg( hDevice,REG_FTS_MAX_DELAY_SPREAD_L, &maxDelayL );
		maxDelayVal = (MXD_UINT16)(maxDelayH<<8) + maxDelayL;
		if( maxDelayVal<500 )
		{
			return MXD_NORMAL_DELAY;
		}           
	}

	MXD_EX_ReadReg( hDevice, REG_MISC_INT_STATUS, &regVal );
	if( REG_QBL_IR_REFFW_STATUS_BIT == (regVal&REG_QBL_IR_REFFW_STATUS_BIT))
	{
		MXD_DebugPrint( "DCC_GetSystemStatus:: Qam autoscale error !\n" );

		MXD_EX_WriteReg( hDevice, REG_MISC_INT_CLEAR, REG_QBL_IR_REFFW_CLEAR_BIT );
	}

	DTP_GetBler( hDevice, &blerVal, &blerWindow );
	if( 0 != blerWindow )
	{
		bler = blerVal*100/blerWindow;
	}
	if( bler> BLER_THLD )
	{        
		if( !pDevice->bBigDelayStatus )
		{
			MXD_EX_ReadReg( hDevice,REG_FTS_MAX_DELAY_SPREAD_H, &maxDelayH );
			MXD_EX_ReadReg( hDevice,REG_FTS_MAX_DELAY_SPREAD_L, &maxDelayL );
			maxDelayVal = (MXD_UINT16)(maxDelayH<<8) + maxDelayL;
			MXD_EX_ReadReg( hDevice,REG_FTS_SECONDARY_PATH_H, &secondPathH );
			MXD_EX_ReadReg( hDevice,REG_FTS_SECONDARY_PATH_L, &secondPathL );
			secondPathVal = (MXD_UINT16)(secondPathH<<8) + secondPathL;
			if( (maxDelayVal>512)&&(secondPathVal<80))
			{
				pDevice->bBigDelayStatus = TRUE;
				MXD_DebugPrint( "DCC_GetSystemStatus:: max delay is %d, second path is %d!\n",maxDelayVal,secondPathVal);
				return MXD_BIG_DELAY;
			}
		}

		MXD_DebugPrint( "DCC_GetSystemStatus:: bler is %d at time:%d!\n",bler,DCC_GetTickCount( hDevice ));
		eRtnCode = MXD_POOR_SIGNAL;
	}
	else
	{
		pDevice->ServiceSearchParam.nRefTick = 0;
	}
	return eRtnCode;
}

/*!
* \par Description
* This function is used to search frequency.
*
* \param hDevice	[IN] the handle of chip device which host is operating;
*
* \return Return code by MXD_RETURN_CODE enumeration
*
* \warning    
*/

MXD_RETURN_CODE DCC_SearchFrequency( MXD_HANDLE hDevice )
{
	MIRA_DEVICE_HANDLE* pDevice = (MIRA_DEVICE_HANDLE*) hDevice;
	MXD_RETURN_CODE eRtnCode = MXD_GENERAL_ERROR;	

	if( (pDevice->ServiceSearchParam.nCurrentFreqKhz <= pDevice->ServiceSearchParam.nEndFreqKhz)||(pDevice->bStartRecovery) )
	{
		if( (MXD_GENERAL_ERROR == pDevice->ServiceSearchParam.eSearchStatus)&&(!pDevice->bStartRecovery) )
		{
			pDevice->ServiceSearchParam.eSearchStatus = MXD_POLLING_STATUS;
			pDevice->ServiceSearchParam.nStcNum = 0;
			pDevice->ServiceSearchParam.bStcStatus = FALSE;

			pDevice->nReSyncNum = 2;
			//            pDevice->nNormalDelayNum = 0;
			MXD_EX_WriteReg( pDevice, REG_STC_MISC_CTRL,0x0);//disable notch filter;
			DCC_ResetDevice( pDevice );
			MXD_DebugPrint( "DCC_SearchFrequency::Begin to search ________%d_______ KHz!\n",pDevice->ServiceSearchParam.nCurrentFreqKhz );
			eRtnCode = DCC_TuneFrequency( pDevice,pDevice->ServiceSearchParam.nCurrentFreqKhz );
			if( MXD_RTN_OK != eRtnCode )
			{
				MXD_DebugPrint( "DCC_SearchFrequency::Tune Freq error!\n" );
				if( pDevice->ServiceSearchParam.nCurrentFreqKhz > pDevice->ServiceSearchParam.nEndFreqKhz )
				{
					pDevice->bStartServiceSearch = FALSE;
				}
				if( pDevice->m_fnCallbacks.OnServiceSearchResult )
					pDevice->m_fnCallbacks.OnServiceSearchResult( pDevice->nDemodChipIndex, pDevice->ServiceSearchParam.pSearchUserParam, pDevice->ServiceSearchParam.nCurrentFreqKhz, NULL, 0 );
				pDevice->ServiceSearchParam.nCurrentFreqKhz += pDevice->ServiceSearchParam.nStepFreqKhz;
				return eRtnCode;
			}
			if( MXD_RTN_OK != DCC_SyncSignal( pDevice ))
			{
				pDevice->bSystemLockStatus = FALSE;
				return eRtnCode;         
			}
		}
		if( pDevice->bRecoveryStatus )
		{
			pDevice->bRecoveryStatus = FALSE;
			if( MXD_RTN_OK != DCC_SyncSignal( pDevice ))
			{
				pDevice->bSystemLockStatus = FALSE;
				return eRtnCode;         
			}	
		}
		eRtnCode = DCC_IsSignalLocked( pDevice );
		switch( eRtnCode )
		{
		case MXD_RTN_OK:
			pDevice->bSystemLockStatus = TRUE;
			if( pDevice->bStartRecovery )
			{
				pDevice->bRecoveryStatus = FALSE;
				pDevice->bStartRecovery = FALSE;
				pDevice->bStartServiceSearch = FALSE;
			}
			else if( MXD_RTN_OK == pDevice->ServiceSearchParam.eSearchStatus )
			{
				pDevice->ServiceSearchParam.nCurrentFreqKhz += pDevice->ServiceSearchParam.nStepFreqKhz;
				pDevice->ServiceSearchParam.eSearchStatus = MXD_GENERAL_ERROR;
			}
			else if( MXD_CLCHDATA_OK != pDevice->ServiceSearchParam.eSearchStatus )
				pDevice->ServiceSearchParam.eSearchStatus = MXD_CLCHCRC_PASS;

			return MXD_RTN_OK;
			break;

		case MXD_POLLING_STATUS:
			return eRtnCode;
			break;
		case MXD_CTS_FAIL:
		case MXD_CLCHCRC_FAIL:    
		case MXD_POOR_SIGNAL:
			if( pDevice->bStartRecovery )
			{
				pDevice->bStartRecovery = TRUE;
				pDevice->bRecoveryStatus = TRUE;

			}
			else
			{
				if( pDevice->m_fnCallbacks.OnServiceSearchResult )
					pDevice->m_fnCallbacks.OnServiceSearchResult( pDevice->nDemodChipIndex, pDevice->ServiceSearchParam.pSearchUserParam, pDevice->ServiceSearchParam.nCurrentFreqKhz, NULL, 0 );
				pDevice->ServiceSearchParam.nCurrentFreqKhz += pDevice->ServiceSearchParam.nStepFreqKhz;
				pDevice->ServiceSearchParam.eSearchStatus = MXD_GENERAL_ERROR;
			}
			return eRtnCode;		    
			break;

		default:
			break;	    
		}

	}
	else
	{
		pDevice->bStartServiceSearch = FALSE;
		return MXD_RTN_OK;
	}
	return eRtnCode;

}

/***********************************************************************************************
*
* SPI Section
* - MXD_SetupMxdSpi
* - MXD_StopMxdSpi
* - MXD_SpiCmd52
* - MXD_SpiCmd53
* - MXD_MasterSpiTxRx
*
***********************************************************************************************
*/

/*!
* \par Description
* Setup maxscend slave SPI interface, and enable MAC layer of maxscend slave SPI interface.
*
* \param hDevice    [ in ] Handle of the device
*
* \return Return code by MXD_RETURN_CODE enumeration
*
*
* \remarks:
*
*/
MXD_RETURN_CODE MXD_API DDS_SetupMxdSpi ( MXD_HANDLE hDevice )
{
	MXD_RETURN_CODE eRtnCode = MXD_GENERAL_ERROR;
	MIRA_DEVICE_HANDLE* pDevice = (MIRA_DEVICE_HANDLE*) hDevice;

	MXD_UINT8 cmd0[6] = { 0x40, 0x00, 0x00, 0x00, 0x00, 0x01 };
	MXD_UINT8 cmd5_0[6] = { 0x45, 0x00, 0x00, 0x00, 0x00, 0x01 };
	MXD_UINT8 cmd5_OCR[6] = { 0x45, 0x00, (MXD_UINT8)( OCR >> 16 ), (MXD_UINT8)(OCR >> 8), (MXD_UINT8)( OCR ), 0x01 };
	MXD_UINT8 spiTxBuf[32]= { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
		0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
	//MXD_UINT8 spiRxBuf[32]= { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
	//                     0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
	MXD_UINT8 i, j;

	for(i = 0; i < 6; i++ )             /*send the spi cmd0*/
	{
		spiTxBuf[ i ] = cmd0[ i ];
	}
	MXD_Memcpy( pDevice->pDevTxBuffer, spiTxBuf, 32 );
	MXD_Memset( pDevice->pDevRxBuffer, 0xff, 32 );
	eRtnCode = DDS_MasterSpiTxRx( hDevice, 7, pDevice->pDevTxBuffer, 32, pDevice->pDevRxBuffer);

	for(i = 0; i < 6; i++)              /*send the spi cmd5_0*/
	{
		spiTxBuf[ i ] = cmd5_0[ i ];
	}
	MXD_Memcpy( pDevice->pDevTxBuffer, spiTxBuf, 32 );
	MXD_Memset( pDevice->pDevRxBuffer, 0xff, 32 );
	eRtnCode = DDS_MasterSpiTxRx( hDevice, 7, pDevice->pDevTxBuffer, 32, pDevice->pDevRxBuffer);
#ifdef __SPI_CHECK__
	for (i = 4; i < 18; i++ )   /*If not in power on, The response maybe is 16 byte 0xff. */
	{
		if( ( 0x1 == pDevice->pDevRxBuffer[i] ) && ( 0x90 == pDevice->pDevRxBuffer[i+1] ) && ( 0xff==pDevice->pDevRxBuffer[i+2] ) && ( 0xff==pDevice->pDevRxBuffer[i+3] ) && ( 0x00 == pDevice->pDevRxBuffer[i+4] ) )
		{
			break;
		}
		else if( 17 == i )
		{
			MXD_DebugPrint( "the cmd5_0 is failed!, the buf is:\n");
			for( j=0; j<32; j++ )
			{
				MXD_DebugPrint("%x ", pDevice->pDevRxBuffer[j]);
			}
			MXD_DebugPrint("\n");
			return MXD_GENERAL_ERROR;
		}
	}
#endif

	for(i = 0; i < 6; i++)              /*send the spi cmd5_0*/
	{
		spiTxBuf[ i ] = cmd5_OCR[ i ];
	}
	MXD_Memcpy( pDevice->pDevTxBuffer, spiTxBuf, 32 );
	MXD_Memset( pDevice->pDevRxBuffer, 0xff, 32 );
	eRtnCode = DDS_MasterSpiTxRx( hDevice, 7, pDevice->pDevTxBuffer, 32, pDevice->pDevRxBuffer );
#ifdef __SPI_CHECK__
	for (i = 4; i < 18; i++ )       /*If not in power on, The response maybe is 16 byte 0xff. */
	{
		if( ( 0x00 == pDevice->pDevRxBuffer[i] ) && ( 0x90 == pDevice->pDevRxBuffer[i+1] ) && ( 0xff==pDevice->pDevRxBuffer[i+2] ) && ( 0xff==pDevice->pDevRxBuffer[i+3] ) && ( 0x00 == pDevice->pDevRxBuffer[i+4] ) )
		{
			break;
		}else if( 17 == i )
		{
			MXD_DebugPrint( "DDS_SetupMxdSpi:: the cmd5_OCR is failed!\n");
			return MXD_GENERAL_ERROR;
		}
	}
#endif

	/*func1 enable write to set 0x02(func0).bit1 */
	eRtnCode = DDS_SpiCmd52( hDevice, CTRL_PATH_READREG, REG_PAGE_FUNC0, 0x2, &i);
	i |= 0x02;
	eRtnCode = DDS_SpiCmd52( hDevice, CTRL_PATH_WRITEREG, REG_PAGE_FUNC0, 0x2, &i);

	if( INT_USE_SPI_MAC == pDevice->tDeviceConfig.nIntType )
	{
		/*REG_PAGE_FUNC1 interrupt enable and Interrupt pin enable */
		eRtnCode = DDS_SpiCmd52( hDevice, CTRL_PATH_READREG, REG_PAGE_FUNC0, 0x04, &i );
		i |= 0x03;
		eRtnCode = DDS_SpiCmd52( hDevice, CTRL_PATH_WRITEREG, REG_PAGE_FUNC0, 0x04, &i );

		/* Enable continuous SPI INT */
		eRtnCode = DDS_SpiCmd52( hDevice, CTRL_PATH_READREG, REG_PAGE_FUNC0, 0x07, &i );
		i |= 0xa0;
		eRtnCode = DDS_SpiCmd52( hDevice, CTRL_PATH_WRITEREG, REG_PAGE_FUNC0, 0x07, &i );
	}
	return eRtnCode;
}/* end of DDS_SetupMxdSpi( ) */

/*!
* \par Description
* Stop and set it into idle state.
*
* \param hDevice    [ in ] Handle of the device
*
* \return Return code by MXD_RETURN_CODE enumeration
*
*
* \remarks:
*
*/
MXD_RETURN_CODE MXD_API DDS_StopMxdSpi ( MXD_HANDLE hDevice )
{
	MXD_RETURN_CODE eRtnCode = MXD_RTN_OK;
	MXD_UINT8 regVal;

	eRtnCode = DDS_SpiCmd52( hDevice, CTRL_PATH_READREG,  REG_PAGE_FUNC0,  SPI_MAC_RESET_REG, &regVal );
	regVal = UTIL_BitSet( regVal, 0x03, 1, 0x01);
	eRtnCode = DDS_SpiCmd52( hDevice, CTRL_PATH_WRITEREG,  REG_PAGE_FUNC0,  SPI_MAC_RESET_REG, &regVal );
	return eRtnCode;
}/* end of DDS_StopMxdSpi( ) */

/*!
* \par Description
* Cmd52 in MAC layer of maxscend SPI interface, and it is for byte read/write.
*
* \param hDevice       [ in ] Handle of the device
* \param rwIndicator   [ in ] Read/Write Indicator. ( SPI_BYTE_READ and SPI_BYTE_WRITE )
* \param regFuncNum    [ in ] Register function/page no. to be read.
* \param regAddr               [ in ] Register address to be read.
* \param pRegVal               [ inout ] Pointer to the register value, which will be written or should be read.
*
* \return Return code by MXD_RETURN_CODE enumeration
*
*
* \remarks:
*   Response5 format is:
*             ЩЩЩЩЩЩЩЩ
*              0  0       0   R/W data(8bits)     
*             ةةةةةةةة
*              For more detail to see Page22 of SimplifiedSDIOCardSpecification1.10
*
*/

MXD_RETURN_CODE MXD_API DDS_SpiCmd52( MXD_HANDLE hDevice, MXD_UINT8 rwIndicator, MXD_UINT8 regFuncNum, MXD_UINT32 regAddr, MXD_UINT8 *pRegVal )
{
	MXD_RETURN_CODE eRtnCode = MXD_GENERAL_ERROR;
	MXD_UINT8 stuffBit = 0;
	MXD_UINT8 rawFlag = 0;
	MXD_UINT8 crc7Bit = 0;
	MXD_UINT8 startBit =0;
	MXD_UINT8 endBit= 1;
	MXD_UINT8 directionBit =1;
	MXD_UINT8 cmdIndx = 52;
	MXD_UINT8 spiTxBuf[32] = {0x0ff,0xff,0x0ff,0xff,0x0ff,0xff,0x0ff,0xff,0x0ff,0xff,0x0ff,0xff,0x0ff,0xff,0x0ff,0xff,
		0x0ff,0xff,0x0ff,0xff,0x0ff,0xff,0x0ff,0xff,0x0ff,0xff,0x0ff,0xff,0x0ff,0xff,0x0ff,0xff};
	//    MXD_UINT8 spiRxBuf[32] = {0x0ff,0xff,0x0ff,0xff,0x0ff,0xff,0x0ff,0xff,0x0ff,0xff,0x0ff,0xff,0x0ff,0xff,0x0ff,0xff,
	//                                               0x0ff,0xff,0x0ff,0xff,0x0ff,0xff,0x0ff,0xff,0x0ff,0xff,0x0ff,0xff,0x0ff,0xff,0x0ff,0xff};
	MXD_UINT8 cmd52[6] = {0, 0, 0, 0, 0, 0};
	MXD_UINT8 j;
	MIRA_DEVICE_HANDLE* pDevice = (MIRA_DEVICE_HANDLE*) hDevice;

	if ( (regFuncNum>REG_PAGE_FUNC1) || (rwIndicator > CTRL_PATH_WRITEREG) || ( (regFuncNum == REG_PAGE_FUNC1 ) && (regAddr>0x00ff)))
	{
		MXD_DebugPrint( "DDS_MxdSpiCmd52:: the argument is error!\n");
		return MXD_GENERAL_ERROR;
	}

	/*Packet CMD52*/
	cmd52[0] = (MXD_UINT8)((startBit<<7)|(directionBit<<6)|(cmdIndx));/*0<<7 |        1<<6         | 110100*/

	/*Read = 0   | FuncNumber 3bit |    0         |    0     |  Addr High 2 bits */
	cmd52[1] = (MXD_UINT8)((rwIndicator<<7) | (regFuncNum<<4) | (rawFlag<<3) | stuffBit |(MXD_UINT8)(regAddr>>15));

	cmd52[2] = (MXD_UINT8)(regAddr>>7) & 0x0ff;

	cmd52[3] = ( (MXD_UINT8)(regAddr<<1)&0x0ff )| stuffBit;

	if( CTRL_PATH_READREG== rwIndicator )
	{
		cmd52[4] = 0;
	}
	else
	{
		cmd52[4] =  *pRegVal;
	}

	cmd52[5] =  ((MXD_UINT8)(crc7Bit<<1)|endBit);          /* Default the chip work on NO-CRC mode.*/

	for(j = 0; j < 6; j++ )    /* Packet CMD52_IO_RW_DIRECT & Response(SPI mode)*/
	{
		spiTxBuf[ j ] = cmd52[j ];
	}
	MXD_Memcpy( pDevice->pDevTxBuffer, spiTxBuf, 32 );
	MXD_Memset( pDevice->pDevRxBuffer, 0xff, 32 );
	eRtnCode = DDS_MasterSpiTxRx( hDevice, 7, pDevice->pDevTxBuffer, 32, pDevice->pDevRxBuffer );

	/*
	* when reset spi via function0 register 0x06, no response,return ok!
	*/
	if( ( SPI_MAC_RESET_REG == regAddr ) && ( REG_PAGE_FUNC0 == regFuncNum ) &&  ( CTRL_PATH_WRITEREG == rwIndicator ) )
	{
		return MXD_RTN_OK;
	}

	j =0;
	while (0xff == pDevice->pDevRxBuffer[j])
	{
		if (j > 14)
		{
			return MXD_GENERAL_ERROR;        /*MXD_RTN_CMD52_ERR;*/
		}
		j++;
	}

	if( ( CTRL_PATH_READREG == rwIndicator ) && ( 0x00 == pDevice->pDevRxBuffer[ j ] ) )
	{
		*pRegVal = pDevice->pDevRxBuffer[j+1];
	}
	return eRtnCode;
}/* end of DDS_SpiCmd52( ) */

/*!
* \par Description
* Cmd53 in MAC layer of maxscend SPI interface, and it is for burst read only.
*
* \param hDevice               [ in ] Handle of the device
* \param rwFlag				[ in ] read / write flag: ( SPI_READ_FLAG and SPI_WRITE_FLAG )
* \param burstMode             [ in ] Burst read mode: ( BLOCK_MODE and MULTIBYTE_MODE )
* \param bufferAddr            [ in ] On-chip buffer address to be read.
* \param byteCnt                       [ in ] Bytes to be read, it should be even.
* \param pBurstDataIn          [ out ] Pointer to the burst data after reading.
*
* \return Return code by MXD_RETURN_CODE enumeration
*
*
* \remarks:
*
*/
MXD_RETURN_CODE MXD_API DDS_SpiCmd53 ( MXD_HANDLE hDevice, MXD_UINT8 rwFlag, MXD_UINT8 burstMode, MXD_UINT32 bufferAddr, MXD_UINT16 byteCnt, MXD_UINT8 *pBurstDataIn )
{
	MXD_RETURN_CODE eRtnCode = MXD_GENERAL_ERROR;
	MIRA_DEVICE_HANDLE* pDevice = (MIRA_DEVICE_HANDLE*) hDevice;
	const MXD_UINT8 startBit = 0;                                          /* start flag*/
	const MXD_UINT8 endBit = 1;                                            /* end flag*/
	const MXD_UINT8 directionBit = 1;                                      /* host to mxd*/
	const MXD_UINT8 cmdIndx = 53;                                  /* cmd53*/
	//    const MXD_UINT8 rwFlag = 0;                                            /* read*/
	const MXD_UINT8 funcNum = REG_PAGE_FUNC1;              /* function 1*/
	const MXD_UINT8 incAddr = SPI_FIXED_ADDRESS;   /*Fixed Address access*/
	const MXD_UINT8 crc7Bit = 0;                                            /* CRC 7 bits data, default no CRC Enable by cmd59?*/
	MXD_UINT8 cmd53[6] = {0, 0, 0, 0, 0, 0};
	MXD_UINT32 txLen;
	MXD_INT32 j = 0;
	MXD_UINT16 byteBlockCount = 0;
	MXD_UINT8  tmp;

	if (1 == (byteCnt & 0x01))    /* Not support odd count number*/
	{
		return MXD_GENERAL_ERROR;
	}

	if (BLOCK_MODE == burstMode)
	{
		byteBlockCount = 1;
		/* set cmd53 read block length*/
		tmp = ( MXD_UINT8 )( byteCnt & 0xff );
		eRtnCode = DDS_SpiCmd52( hDevice, CTRL_PATH_WRITEREG, REG_PAGE_FUNC0, 0x110, &tmp );
		tmp =  (MXD_UINT8 )( byteCnt >> 8 );
		eRtnCode = DDS_SpiCmd52( hDevice, CTRL_PATH_WRITEREG, REG_PAGE_FUNC0, 0x111, &tmp );
	}
	else if (MULTIBYTE_MODE == burstMode)
	{
		if( (byteCnt <=  512) && (byteCnt >0) )
		{
			byteBlockCount = byteCnt & 0x1ff;
		}
		else
		{
			return MXD_GENERAL_ERROR;   /*Multibyte-read only support 1~512.*/
		}
	}
	else
	{
		return MXD_GENERAL_ERROR;
	}

	txLen = LENGTH_CMD53_NCR_R5_NAC + byteCnt;
	MXD_Memset( pDevice->pDevTxBuffer, 0xff, txLen );
	MXD_Memset( pDevice->pDevRxBuffer, 0x0, txLen );

	/* packet CMD53;       0<<7      |             1<<6  |  110101*/
	cmd53[0] = (startBit<<7) | (directionBit<<6) | (cmdIndx);

	/* 0:Read   |              |  1:blockmode   | 0:Inc       |  Addr High bit16,15 */
	cmd53[1] = (MXD_UINT8)((rwFlag<<7) | (funcNum<<4) | (burstMode<<3) |(incAddr<<2) | (MXD_UINT8)(bufferAddr>>15));

	/* Addr bit14:7*/
	cmd53[2] = (MXD_UINT8)(bufferAddr>>7)&0x0ff;

	/* Addr bit6:0         |  byteBlockCount: bit8             */
	cmd53[3] = ((MXD_UINT8)(bufferAddr<<1)&0x0ff) | ((MXD_UINT8)(byteBlockCount>>8));

	/*    byteBlockCount: bit7:0*/
	cmd53[4] = (MXD_UINT8)(0xff&byteBlockCount);

	/* default the chip work on NO-CRC mode.*/
	cmd53[5] =  ( crc7Bit<<1 ) | ( endBit );

	/* R5, cmd53 Response(SPI mode)*/
	for(j = 0; j < 6; j++ )
	{
		pDevice->pDevTxBuffer[ j ] = cmd53[j ];
	}

	/* hardware implement*/
	eRtnCode = DDS_MasterSpiTxRx(hDevice, 7, pDevice->pDevTxBuffer,txLen, pDevice->pDevRxBuffer );
	if( 0 == rwFlag ) /* block read*/
	{
		while (0xff == pDevice->pDevRxBuffer[j])
		{       /*  ++ untill receive R5 */
			if (j>14)
			{
				return MXD_GENERAL_ERROR;
			}
			j++;
		}
		while ( 0xfe != pDevice->pDevRxBuffer[j] )
		{       /*  ++ untill receive DataHead */
			if (j>24)
			{
				return MXD_GENERAL_ERROR;
			}
			j++;
		}
		j++;

		MXD_Memcpy(pBurstDataIn, ( pDevice->pDevRxBuffer+j), txLen-LENGTH_CMD53_NCR_R5_NAC);
	}
	else
	{
		j = 0;
		while (0xff == pDevice->pDevRxBuffer[j])
		{       /*  ++ untill receive R5 */
			if (j>14)
			{
				return MXD_GENERAL_ERROR;
			}
			j++;
		}
		while ( 0xff != pDevice->pDevRxBuffer[j] )
		{       /*  ++ untill receive DataHead */
			if (j>24)
			{
				return MXD_GENERAL_ERROR;
			}
			j++;
		}
		j++;
		MXD_Memset( pDevice->pDevTxBuffer, 0xff, byteCnt+1+4 );
		MXD_Memset( pDevice->pDevRxBuffer, 0xff, byteCnt+1+4 );
		pDevice->pDevTxBuffer[0] = 0xfe;
		for( j=1;j<=byteCnt;j++ )
		{
			pDevice->pDevTxBuffer[j] = *pBurstDataIn ++; 
		}

		/*for CRC check*/
		pDevice->pDevTxBuffer[j+1] = 0xff;
		pDevice->pDevTxBuffer[j+2] = 0xff;
		pDevice->pDevTxBuffer[j+3] = 0xff;
		pDevice->pDevTxBuffer[j+4] = 0xff;
		eRtnCode = DDS_MasterSpiTxRx(hDevice,(byteCnt+1+1), pDevice->pDevTxBuffer,byteCnt+1+4,pDevice->pDevRxBuffer);

		j=0;
		while (0xff == pDevice->pDevRxBuffer[j])
		{       /*  ++ untill receive R5 */
			if (j>=byteCnt+1+4)
			{
				return MXD_GENERAL_ERROR;
			}
			j++;
		}
		while ( 0xe5 != pDevice->pDevRxBuffer[j] )
		{       /*  ++ untill receive DataHead */
			if (j>24)
			{
				return MXD_GENERAL_ERROR;
			}
			j++;
		}
	}
	return eRtnCode;
}/* end of DDS_SpiCmd53( ) */

/*!
* \par Description
* Tx/Rx of master SPI, it will be porting according to different host processor.
*
* \param hDevice               [ in ] Handle of the device
* \param trxLen                        [ in ] length to be txed or rxed
* \param pDataOut              [ in ] pointer to the data to be txed.
* \param pDataIn                       [ out ] pointer to the data to be rxed.
*
* \return Return code by MHL_DRV_RTN_CODE_E enumeration
*
*
* \remarks: it will be porting according to different host processor.
*
*/
MXD_RETURN_CODE MXD_API DDS_MasterSpiTxRx( MXD_HANDLE hDevice, MXD_UINT32 trxLen, MXD_UINT8 *pDataOut, MXD_UINT32 revLen, MXD_UINT8 *pDataIn )
{
	MIRA_DEVICE_HANDLE* pDevice = (MIRA_DEVICE_HANDLE*) hDevice;
	return MxdPorting_SPI_TxRx( pDevice->nDemodChipIndex, trxLen, pDataOut, revLen, pDataIn );
}/* end of DDS_MasterSpiTxRx( ) */


/*!
* \par Description
* Read the register of MXD chip and Get certain consequent bit value.
*
*\param hDevice                        [ in ]          the device handle.
* \param regAddr                       [ in ]          Register address to be read.
* \param bitOffset                     [ in ]          Bit offset of this register to be read, MSB 0x07 C 0x00 LSB.
* \param bitCnt                        [ in ]          Bit count to be read, 0x08 C 0x01.
* \param pRegVal                       [ out ]         Register value
*
* \return Return code by MXD_RETURN_CODE enumeration.
*
* \remark: 
*
*/
MXD_RETURN_CODE MXD_ReadRegFields ( 
								   MXD_HANDLE hDevice, 
								   MXD_UINT32 regAddr, 
								   MXD_UINT8 bitOffset, 
								   MXD_UINT8 bitCnt, 
								   MXD_UINT8 *pRegVal )
{
	MXD_UINT8 rdData = 0;
	MXD_UINT8 i;

	MXD_EX_ReadReg( hDevice, regAddr,pRegVal );
	for( i = 0; i < bitCnt; i++)
	{
		rdData |= (MXD_UINT8)( ( ( ( *pRegVal ) >> bitOffset ) & ((MXD_UINT8)0x01)) << i );
		bitOffset++;
	}
	*pRegVal = rdData;

	return MXD_RTN_OK;
}/* end of MXD_ReadRegFields( ) */

/*!
* \par Description
* Write the register of MXD chip with certain bit.
*
* \param hDevice                        [ in ]          the device handle.
* \param regAddr                       [ in ]          Register address to be read.
* \param bitOffset                     [ in ]          Bit offset of this register to be read, MSB 0x07 C 0x00 LSB.
* \param bitCnt                        [ in ]          Bit count to be read, 0x08 C 0x01.
* \param regVal                        [ in ]          Register value
*
* \return Return code by MXD_RETURN_CODE enumeration.
*
* \remark: 
*
*/
MXD_RETURN_CODE MXD_WriteRegFields (
									MXD_HANDLE hDevice, 
									MXD_UINT32 regAddr, 
									MXD_UINT8 bitOffset, 
									MXD_UINT8 bitCnt, 
									MXD_UINT8 regVal )
{
	MXD_UINT8 wrData;
	MXD_UINT8 value;

	MXD_EX_ReadReg( hDevice, regAddr, &value );
	wrData = UTIL_BitSet( value, bitOffset, bitCnt, regVal);            

	return MXD_EX_WriteReg( hDevice, regAddr, wrData );

}/* end of MXD_WriteRegFields( )*/

/*!
* \par Description
* set data with certain bit.
*
* \param inputVal                      [ in ]          Register value
* \param bitOffset                     [ in ]          Bit offset of this register to be read, MSB 0x07 C 0x00 LSB.
* \param bitCnt                        [ in ]          Bit count to be read, 0x08 C 0x01.
* \param setVal                        [ in ]          the value to be set to the certain bit. 
*
* \return Return code MXD_UINT8;
*
* \remark: 
*
*/
MXD_UINT8 UTIL_BitSet( 
					  MXD_UINT8 inputVal, 
					  MXD_UINT8 bitOffset, 
					  MXD_UINT8 bitCnt, 
					  MXD_UINT8 setVal)
{
	MXD_UINT8 i;
	MXD_UINT8 offsetVal;

	offsetVal= bitOffset;
	for( i=0; i<bitCnt; i++ )
	{/* set the bit value of data 0 */
		inputVal = inputVal & ( ~(MXD_UINT8)( 1 << bitOffset ) );  
		bitOffset++;
	}       
	inputVal = inputVal | (MXD_UINT8)( ( setVal  << offsetVal ) );
	return inputVal;
}/* end of bitSet( ) */

/*!
* \par Description
* Caculate Bloc Nums for service.
*
*\ param hDevice                        [ in ]          the device handle.
* \param serviceID                       [ in ]         service id.
*
* \return Return code MXD_RETURN_CODE;
*
* \remark: 
*
*/

MXD_RETURN_CODE DTP_CaculateBockNum(MXD_HANDLE hDevice, MXD_UINT32 serviceID)
{
	MIRA_DEVICE_HANDLE* pDevice = NULL;
	MXD_CMMBSERVICE_INFO* pCmmbServiceInfo = NULL;
	MXD_UINT8  i = 0;
	MXD_UINT8  m_qamType = 0;
	//  MXD_UINT8  m_codeRate = 0;
	MXD_UINT8  m_inerleaveMode = 0;
	//  MXD_UINT8  m_rsmode = 0;
	MXD_UINT8  m_DeblocNumPerBY = 0;
	MXD_UINT8  m_TsNum = 0;
	MXD_UINT8  m_DeInerBloc = 0;
	MXD_UINT8  m_memBlocNum = 0;
	MXD_UINT8  m_IDeInterleave = 0;
	MXD_UINT8  m_FDeInterleave = 0;
	if (hDevice == NULL)
	{
		return MXD_GENERAL_ERROR;
	}
	pDevice = (MIRA_DEVICE_HANDLE*) hDevice;
	pCmmbServiceInfo = ((MXD_DEMUXER_CONTEXT*)pDevice->pDemuxerPrivateStruct)->m_pSeviceChannelList;
	for( i = 0; i < ((MXD_DEMUXER_CONTEXT*)pDevice->pDemuxerPrivateStruct)->m_nServiceCount; i++)
	{
		if (serviceID == pCmmbServiceInfo->nServiceID )
		{
			break;
		}
		pCmmbServiceInfo++;
	}
	switch(pCmmbServiceInfo->eModuType)
	{
	case 0:
		m_qamType = 1;
		break;
	case 1:
		m_qamType = 2;
		break;
	case 2:
		m_qamType = 4;
		break;
	default:
		MXD_DebugPrint("MXD_CaculateBockNum:illegal qamType!\n");
		break;
	}
	switch(pCmmbServiceInfo->eInterleaveMode)
	{
	case 0:
	case 1:
		m_inerleaveMode = 1;
		break;
	case 2:
		m_inerleaveMode = 2;
		break;
	case 3:
		m_inerleaveMode = 4;
		break;
	default:
		MXD_DebugPrint("MXD_CaculateBockNum:illegal Interleave mode!\n");
		break;
	}

	m_DeblocNumPerBY = (m_inerleaveMode*2/m_qamType);     //(m_qamType*1/pCmmbServiceInfo->eInterleaveMode*0.5)
	m_TsNum = pCmmbServiceInfo->nTsCount;

	if (m_DeblocNumPerBY > 0)
	{
		m_IDeInterleave =  m_TsNum/m_DeblocNumPerBY;        //int
		m_FDeInterleave =  m_TsNum%m_DeblocNumPerBY;        //Fac
	}
	else
	{
		m_IDeInterleave = m_TsNum * 2;
		m_FDeInterleave = 0;
	}

	if (m_IDeInterleave == 0) 
	{
		while (m_IDeInterleave == 0) 
		{
			m_TsNum = m_TsNum + m_FDeInterleave;
			m_IDeInterleave =  m_TsNum / m_DeblocNumPerBY;      //int
			m_FDeInterleave =  m_TsNum % m_DeblocNumPerBY;      //Fac
		}
		if (0 == m_FDeInterleave)
			m_DeInerBloc = m_IDeInterleave;
		else
			m_DeInerBloc = m_IDeInterleave + 1;

	}
	else 
	{
		if (0 == m_FDeInterleave)
		{
			m_DeInerBloc = m_IDeInterleave;
		}
		else 
		{
			m_TsNum = m_TsNum + m_FDeInterleave;
			m_IDeInterleave =  m_TsNum / m_DeblocNumPerBY;      //int
			m_FDeInterleave =  m_TsNum % m_DeblocNumPerBY;      //Fac
			if (0 == m_FDeInterleave)
				m_DeInerBloc = m_IDeInterleave;
			else
				m_DeInerBloc = m_IDeInterleave + 1;
		}
	}
	switch (m_inerleaveMode)//Byte De-Interleave
	{
	case 1: 
		m_memBlocNum = (pCmmbServiceInfo->eLdpcMode==0) ? m_DeInerBloc*2 : m_DeInerBloc*3;
		break;
	case 2: 
		m_memBlocNum = (pCmmbServiceInfo->eLdpcMode==0) ? m_DeInerBloc*4 : m_DeInerBloc*6;
		break;
	case 4: 
		m_memBlocNum = (pCmmbServiceInfo->eLdpcMode==0) ? m_DeInerBloc*8 : m_DeInerBloc*12;
		break;
	default:
		MXD_DebugPrint(" MXD_CaculateBockNum:illegal Interleave mode!\n ");
		break;
	}
	//for ts mode
	if (pDevice->tDeviceConfig.eDataPath == MXD_TS)
	{
		if (m_memBlocNum > 24) // >24 memory bloc
		{
			MXD_DebugPrint(" MXD_CaculateBockNum:only for TS mode!\n ");
			m_DeInerBloc = 2;
			switch(m_inerleaveMode)
			{
			case 1: 
				m_memBlocNum = (pCmmbServiceInfo->eLdpcMode==0) ? 4:6;
				break;
			case 2: 
				m_memBlocNum = (pCmmbServiceInfo->eLdpcMode==0) ? 8:12;
				break;
			case 4: 
				m_memBlocNum = (pCmmbServiceInfo->eLdpcMode==0) ? 16:24;
				break;
			default:
				break;
			}
		}
	}
	return m_memBlocNum;
}

/*!
* \par Description
* DTP set LDPC/RS Window
*
*\ param hDevice                        [ in ]          the device handle.
*
* \return Return code MXD_RETURN_CODE;
*
* \remark: 
*
*/

MXD_RETURN_CODE DTP_SetLDPCRSWindow(MXD_HANDLE hDevice)
{
	MIRA_DEVICE_HANDLE* pDevice = NULL;
	MXD_CMMBSERVICE_INFO* pCmmbServiceInfo = NULL;

	MXD_UINT8  m_qamType = 0;
	//  MXD_UINT8  m_codeRate = 0;
	//MXD_UINT8  m_inerleaveMode = 0;
	MXD_UINT16 m_rsmode = 0;
	MXD_UINT16 m_rswindow = 0;
	MXD_UINT8  m_ldpcwindow = 0;
	//  MXD_UINT8  m_schDataThr = 0;
	MXD_UINT8  i, j = 0;
	MXD_BOOL   m_setFlag = 0;
	MXD_UINT8 maxService = 0;
	MXD_UINT8 maxCurMode = 0;
	MXD_UINT8 curMode = 0;
	MXD_UINT8 regVal = 0;

	if (hDevice == NULL)
	{
		return MXD_GENERAL_ERROR;
	}
	pDevice = (MIRA_DEVICE_HANDLE*) hDevice;
	for( i=0; i<6; i++ )
	{
		if( pDevice->ActiveService[i].nActiveServiceID != 0&& pDevice->ActiveService[i].nActiveServiceID != 0xffff)
		{
			pCmmbServiceInfo = ((MXD_DEMUXER_CONTEXT*)pDevice->pDemuxerPrivateStruct)->m_pSeviceChannelList;
			for( j = 0;j < ((MXD_DEMUXER_CONTEXT*)pDevice->pDemuxerPrivateStruct)->m_nServiceCount; j++)
			{
				if (pDevice->ActiveService[i].nActiveServiceID == pCmmbServiceInfo->nServiceID )
				{
					break;
				}
				pCmmbServiceInfo++;
			}
			switch(pCmmbServiceInfo->eModuType)
			{
			case MXD_MODULATE_TYPE_BPSK://BPSK
				m_qamType = 1;
				m_rsmode = (pCmmbServiceInfo->eLdpcMode==0)?pCmmbServiceInfo->nTsCount*2:pCmmbServiceInfo->nTsCount*3;
				break;
			case MXD_MODULATE_TYPE_QPSK://QPSK
				m_qamType = 2;
				m_rsmode = (pCmmbServiceInfo->eLdpcMode==0)?pCmmbServiceInfo->nTsCount*4:pCmmbServiceInfo->nTsCount*6;
				break;
			case MXD_MODULATE_TYPE_16QAM://16QAM
				//set LDPC
				m_qamType = 4;
				m_rsmode = (pCmmbServiceInfo->eLdpcMode==0)?pCmmbServiceInfo->nTsCount*8:pCmmbServiceInfo->nTsCount*12;
				break;
			default:
				MXD_DebugPrint("MXD_PlayService:illegal QamType!\n");
				break;
			}
			m_ldpcwindow += pCmmbServiceInfo->nTsCount * m_qamType;
			m_rswindow   += m_rsmode;
			if (!m_setFlag)
			{
				//set active tracking TS
				MXD_WriteRegFields(	hDevice, REG_SFO_TRACK_CFG, 0, 5 ,pCmmbServiceInfo->nStartTs);
				m_setFlag = TRUE;
			}
		}
		else if (pDevice->ActiveService[i].nActiveServiceID == 0xffff)
		{
			MXD_WriteRegFields(	hDevice, REG_SFO_TRACK_CFG, 0, 5 ,0);
			m_ldpcwindow  += 1;
			m_rswindow     += 2;
		}
		else
		{
		}
	}
	//set concatenate rs err threshold 
	MXD_EX_WriteReg(pDevice, REG_CONCATENATE_RS_ERR_NUM_L, m_rswindow&0xff);
	MXD_EX_WriteReg(pDevice, REG_CONCATENATE_RS_ERR_NUM_H, (m_rswindow>>8)&0xff);
	//set RS Window
	MXD_EX_WriteReg(pDevice, REG_RS_NUM_L, m_rswindow&0xff);
	MXD_EX_WriteReg(pDevice, REG_RS_NUM_H, (m_rswindow>>8)&0xff);
	//set bler window(LDPC)
	MXD_EX_WriteReg(pDevice, REG_LDPC_STA_SIZE, m_ldpcwindow==0?1:m_ldpcwindow);
	//MXD_DebugPrint("\nSet LDPC window %d \n", m_ldpcwindow);
	//set LDPC iter
	MXD_EX_ReadReg( hDevice, REG_SC_VALID_CFG, &regVal );
	for(i=0;i<5;i++)
	{
		if( 1 == ((regVal>>i)&0x1) )
		{
			switch(i)
			{
			case 0:
				MXD_ReadRegFields( hDevice, REG_SC_INFO_A, 0, 2, &curMode );
				break;
			case 1:
				MXD_ReadRegFields( hDevice, REG_SC_INFO_A, 3, 2, &curMode );
				break;
			case 2:
				MXD_ReadRegFields( hDevice, REG_SC_INFO_B, 0, 2, &curMode );
				break;
			case 3:
				MXD_ReadRegFields( hDevice, REG_SC_INFO_B, 3, 2, &curMode );
				break;
			case 4:
				MXD_ReadRegFields( hDevice, REG_SC_INFO_C, 0, 2, &curMode );
				break;
			}
			if( curMode > maxCurMode   )
			{
				maxCurMode = curMode;
				maxService = i;
			}
		}
	}
	if ((regVal & 0x3F) == 0x00 )
	{
		MXD_EX_WriteReg(pDevice, m_scConfigRegTable[5][1], 0x01 );
		MXD_EX_WriteReg(pDevice, m_scConfigRegTable[5][2], 0x16 );
		MXD_EX_WriteReg(pDevice, REG_SC_VALID_CFG, 0x20 );
		//pDevice->ActiveService[5].nActiveServiceID = 0xFFFF;  
	}
	MXD_WriteRegFields( hDevice,REG_LDPC_CONFIG,0x3,3,maxService );

	return MXD_RTN_OK;
}

/*!
* \par Description
* Get bler
*
* \param hDevice                       [ in ]       the device handle.
* \param m_bler                       [ in ]         block error number.
* \param m_windowSize                 [ in ]         calc window size
*
* \return Return code MXD_RETURN_CODE;
*
* \remark: 
*
*/
MXD_RETURN_CODE DTP_GetBler(MXD_HANDLE hDevice,MXD_UINT16* m_bler, MXD_UINT16* m_windowSize)
{
	MXD_UINT8 m_lblerValue = 0;
	MXD_UINT16 m_hblerValue = 0;
	MXD_UINT16 m_ldpcwindow = 0;
	MIRA_DEVICE_HANDLE* pDevice = NULL;
	if (hDevice == NULL)
	{
		return MXD_GENERAL_ERROR;
	}
	pDevice = (MIRA_DEVICE_HANDLE*) hDevice;

	MXD_WriteRegFields(pDevice,REG_FREEZE_CTRL, 2, 1, 0x01);
	MXD_EX_ReadReg(pDevice, REG_BLER_L, (MXD_UINT8*)&m_lblerValue);
	MXD_EX_ReadReg(pDevice, REG_BLER_H, (MXD_UINT8*)&m_hblerValue);
	MXD_EX_ReadReg(pDevice, REG_LDPC_STA_SIZE, (MXD_UINT8*)&m_ldpcwindow);
	*m_windowSize = m_ldpcwindow*15;
	*m_bler = (MXD_UINT16)((m_hblerValue<<8) + m_lblerValue);
	return MXD_RTN_OK;
}


/*!
* \par Description
* Get RS error count
*
* \param hDevice                       [ in ]       the device handle.
* \
* \aram m_rsError                 [ out ]         RS error count
*
* \return Return code MXD_RETURN_CODE;
*
* \remark: 
*
*/
MXD_RETURN_CODE DTP_GetRSErr(MXD_HANDLE hDevice, MXD_UINT16* m_rsError)
{
	MXD_UINT8  rserr_h;
	MXD_UINT8  rserr_l;
	MXD_UINT8  rserr_head = 0;
	MXD_UINT16 rserr_sum  = 0;
	MXD_UINT8 regVal = 0;
	MXD_UINT8  i = 0;
	MIRA_DEVICE_HANDLE* pDevice = NULL;
	if (hDevice == NULL)
	{
		return MXD_GENERAL_ERROR;
	}
	pDevice = (MIRA_DEVICE_HANDLE*) hDevice;
	for(i=0;i<200;i++)
	{
		MXD_EX_ReadReg(pDevice, REG_RSD_8ERRNUM_H, &rserr_head);
		MXD_EX_ReadReg(pDevice, REG_RSD_8ERRNUM_H, &regVal);
		if( (rserr_head&0xc0) == (regVal&0xc0) )
		{
			MXD_EX_ReadReg(pDevice, REG_RSD_8ERRNUM_L, &rserr_l);
			MXD_EX_ReadReg(pDevice, REG_RSD_8ERRNUM_H, &rserr_h);
			rserr_sum = (MXD_UINT16)((rserr_h&0x3f)<<8) + rserr_l;
			break;
		}
	}
	*m_rsError = rserr_sum;
	return MXD_RTN_OK;
}
/*!
* \par Description
* Get tick count
*
* \param hDevice                       [ in ]       the device handle.
*
* \return Return code MXD_UINT32;
*
* \remark: 
*
*/
MXD_UINT32 DCC_GetTickCount( MXD_HANDLE hDevice )
{
	MXD_UINT8 nTickCount;
	MIRA_DEVICE_HANDLE* pDevice = (MIRA_DEVICE_HANDLE*) hDevice;
	if (hDevice == NULL)
		return 0;
	MXD_EX_ReadReg(pDevice, REG_TIM_VAL, &nTickCount);
	if( pDevice->nTickSaved > nTickCount )
		pDevice->nTickBase += 0x100 + nTickCount - pDevice->nTickSaved;
	else
		pDevice->nTickBase += nTickCount - pDevice->nTickSaved;
	pDevice->nTickSaved = nTickCount;

	return pDevice->nTickBase*25;
}

/*!
* \par Description
* Mxd Sleep function:ms
*
* \param hDevice                       [ in ]       the device handle.
* \param milliSeconds                  [ in ]       ms
*
* \return Return code MXD_RETURN_CODE;
*
* \remark: 
*
*/
MXD_RETURN_CODE DCC_Sleep( MXD_HANDLE hDevice, MXD_INT32 milliSeconds )
{
	if (hDevice == NULL || milliSeconds <= 0)
		return 0;

	if( milliSeconds >= 25 )
	{
		MXD_UINT32 tick = DCC_GetTickCount( hDevice );
		while( DCC_GetTickCount( hDevice ) - tick < (MXD_UINT32)milliSeconds )
			;
	}

	if( milliSeconds%25 > 0 )
	{
		MXD_INT32 i;
		//assume DCC_GetTickCount cost 1 ms?
		for( i=0; i<milliSeconds%25; i++ )
			DCC_GetTickCount( hDevice );
	}
	return MXD_RTN_OK;
}

MXD_RETURN_CODE DTP_StartServiceNameReceive( MXD_HANDLE hDevice )
{
	MIRA_DEVICE_HANDLE* pDevice = (MIRA_DEVICE_HANDLE*) hDevice;
	MXD_UINT32 i;
	MXD_DEMUXER_CONTEXT* pDemuxCtx = (MXD_DEMUXER_CONTEXT*)pDevice->pDemuxerPrivateStruct;
	for( i=0; i<pDemuxCtx->m_nServiceCount; i++ )
	{
		if( pDemuxCtx->m_pSeviceChannelList[i].eServiceType == MXD_CMMBSERVICE_TYPE_ESG )
		{
			MXD_PlayService( hDevice, pDemuxCtx->m_pSeviceChannelList[i].nServiceID, NULL );
			return MXD_RTN_OK;
		}
	}	
	return MXD_GENERAL_ERROR;
}

MXD_RETURN_CODE DTP_StopServiceNameReceive( MXD_HANDLE hDevice )
{
	MIRA_DEVICE_HANDLE* pDevice = (MIRA_DEVICE_HANDLE*) hDevice;
	MXD_UINT32 i;
	MXD_DEMUXER_CONTEXT* pDemuxCtx = (MXD_DEMUXER_CONTEXT*)pDevice->pDemuxerPrivateStruct;
	for( i=0; i<pDemuxCtx->m_nServiceCount; i++ )
	{
		if( pDemuxCtx->m_pSeviceChannelList[i].eServiceType == MXD_CMMBSERVICE_TYPE_ESG )
		{
			MXD_StopService( hDevice, pDemuxCtx->m_pSeviceChannelList[i].nServiceID );
			return MXD_RTN_OK;
		}
	}	
	return MXD_GENERAL_ERROR;
}

void OnStateNULL(MXD_HANDLE hDevice, MIRA_SDK_STATE ePrevState, void* pParam);
void OnStateIdle( MXD_HANDLE hDevice, MIRA_SDK_STATE ePrevState, void* pParam );
void OnStateBeginSearch( MXD_HANDLE hDevice, MIRA_SDK_STATE ePrevState, void* pParam );
void OnStateWaitLock( MXD_HANDLE hDevice, MIRA_SDK_STATE ePrevState, void* pParam );
void OnStateCheckStc( MXD_HANDLE hDevice, MIRA_SDK_STATE ePrevState, void* pParam );
void OnStateGetClch( MXD_HANDLE hDevice, MIRA_SDK_STATE ePrevState, void* pParam );
void OnStateStartEsg( MXD_HANDLE hDevice, MIRA_SDK_STATE ePrevState, void* pParam );
void OnStateEsgReceiving( MXD_HANDLE hDevice, MIRA_SDK_STATE ePrevState, void* pParam );
void OnStateSearchDone( MXD_HANDLE hDevice, MIRA_SDK_STATE ePrevState, void* pParam );
void OnStateDataReceiving( MXD_HANDLE hDevice, MIRA_SDK_STATE ePrevState, void* pParam );
void OnStateStartRecovery( MXD_HANDLE hDevice, MIRA_SDK_STATE ePrevState, void* pParam );
void OnStateWaitRecovery( MXD_HANDLE hDevice, MIRA_SDK_STATE ePrevState, void* pParam );
void OnStateRecoveryDone( MXD_HANDLE hDevice, MIRA_SDK_STATE ePrevState, void* pParam );

#if 0
static MIRA_STATE_STRUCT state_list[] = 
{
	{MIRASTATE_IDLE, OnStateIdle},
	{MIRASTATE_BEGINSEARCH, OnStateBeginSearch},
	{MIRASTATE_WAITLOCK, OnStateWaitLock},
	{MIRASTATE_CHECKSTC, OnStateCheckStc},
	{MIRASTATE_GETCLCH, OnStateGetClch},
	{MIRASTATE_STARTESG, OnStateStartEsg},
	{MIRASTATE_ESGRECEIVING, OnStateEsgReceiving},
	{MIRASTATE_SEARCHDONE, OnStateSearchDone},
	{MIRASTATE_DATARECEIVING, OnStateDataReceiving},
	{MIRASTATE_STARTRECOVERY, OnStateStartRecovery},
	{MIRASTATE_WAITRECOVERY, OnStateWaitRecovery},
	{MIRASTATE_RECOVERYDONE, OnStateRecoveryDone},
};

void STE_StateProcess( MXD_HANDLE hDevice )
{
	MIRA_DEVICE_HANDLE* pDevice = (MIRA_DEVICE_HANDLE*) hDevice;
	MXD_INT32 i;
	if( pDevice->eRequestState != MIRASTATE_NULL )
	{
		for( i=0; i<sizeof(state_list)/sizeof(MIRA_STATE_STRUCT); i++ )
			if( state_list[i].eState == pDevice->eRequestState )
			{
				MIRA_SDK_STATE eState = pDevice->eRequestState;
				pDevice->eRequestState = MIRASTATE_NULL;
				state_list[i].funcState( hDevice, pDevice->eCurrentState, pDevice->pRequestStateParam );
				pDevice->eCurrentState = eState;
			}
	}
	else
	{
		for( i=0; i<sizeof(state_list)/sizeof(MIRA_STATE_STRUCT); i++ )
			if( state_list[i].eState == pDevice->eCurrentState )
				state_list[i].funcState( hDevice, pDevice->eCurrentState, pDevice->pRequestStateParam );
	}
}
#endif

#if 1
static MIRA_STATE_STRUCT state_list[] =
{
	{MIRASTATE_NULL, OnStateNULL},
	{MIRASTATE_IDLE, OnStateIdle},
	{MIRASTATE_BEGINSEARCH, OnStateBeginSearch},
	{MIRASTATE_WAITLOCK, OnStateWaitLock},
	{MIRASTATE_CHECKSTC, OnStateCheckStc},
	{MIRASTATE_GETCLCH, OnStateGetClch},
	{MIRASTATE_STARTESG, OnStateStartEsg},
	{MIRASTATE_ESGRECEIVING, OnStateEsgReceiving},
	{MIRASTATE_SEARCHDONE, OnStateSearchDone},
	{MIRASTATE_DATARECEIVING, OnStateDataReceiving},
	{MIRASTATE_STARTRECOVERY, OnStateStartRecovery},
	{MIRASTATE_WAITRECOVERY, OnStateWaitRecovery},
	{MIRASTATE_RECOVERYDONE, OnStateRecoveryDone},
};

void STE_StateProcess(MXD_HANDLE hDevice)
{
	MIRA_DEVICE_HANDLE* pDevice = (MIRA_DEVICE_HANDLE*) hDevice;
	MXD_INT8 i;
	//  MXD_DebugPrint("\r\nChange from state %d to %d", pDevice->eCurrentState, pDevice->eRequestState);
	if (pDevice->eRequestState != MIRASTATE_NULL)
	{
		//for( i=0; i<sizeof(state_list)/sizeof(MIRA_STATE_STRUCT); i++ )
		//  if( state_list[i].eState == pDevice->eRequestState )
		{
			MIRA_SDK_STATE eState = pDevice->eRequestState;
			pDevice->eRequestState = MIRASTATE_NULL;
			state_list[eState].funcState(hDevice, pDevice->eCurrentState, pDevice->pRequestStateParam);
			pDevice->eCurrentState = eState;
		}
	}
	else
	{
		//  for( i=0; i<sizeof(state_list)/sizeof(MIRA_STATE_STRUCT); i++ )
		//  if( state_list[i].eState == pDevice->eCurrentState )
		state_list[ pDevice->eCurrentState].funcState(hDevice, pDevice->eCurrentState, pDevice->pRequestStateParam);
	}
}
#endif

void OnStateNULL(MXD_HANDLE hDevice, MIRA_SDK_STATE ePrevState, void* pParam)
{
}
void STE_RequestChangeState( MXD_HANDLE hDevice, MIRA_SDK_STATE eState, void* pParam )
{
	MIRA_DEVICE_HANDLE* pDevice = (MIRA_DEVICE_HANDLE*) hDevice;
	//if( pDevice->eRequestState != MIRASTATE_NULL )
	//	MXD_DebugPrint( "Warning! there is unsolved state request %d!\n", pDevice->eRequestState );
	//MXD_DebugPrint( "state request %d!\n", eState );
	pDevice->eRequestState = eState;
	pDevice->pRequestStateParam = pParam;
}

void OnStateIdle( MXD_HANDLE hDevice, MIRA_SDK_STATE ePrevState, void* pParam )
{
	//MXD_UINT8 i = 0;
	MXD_UINT8 uIndex = 0;
	MXD_RETURN_CODE eRtnCode = MXD_RTN_OK;
	MIRA_DEVICE_HANDLE* pDevice = (MIRA_DEVICE_HANDLE*) hDevice;

	//if recovery have not finished, return to recovery status.
	if( ePrevState == MIRASTATE_STARTRECOVERY || ePrevState == MIRASTATE_WAITRECOVERY )
		STE_RequestChangeState( hDevice, MIRASTATE_STARTRECOVERY, NULL );

	if ((pDevice->bSystemLockStatus)&&pDevice->bCLCHEnable)
	{	
		DTP_CheckServiceData(pDevice, &uIndex);
		if (uIndex)
		{
			eRtnCode = DTP_ServiceDataProcess(pDevice, uIndex, FALSE);
		}	  
	}
	//ignore unexpected data interrupt.
	MXD_EX_WriteReg( hDevice, REG_HIC1_INT_CLEAR, 0xff );
}

void OnStateBeginSearch( MXD_HANDLE hDevice, MIRA_SDK_STATE ePrevState, void* pParam )
{
	MXD_RETURN_CODE eRtnCode = MXD_RTN_OK;
	MIRA_DEVICE_HANDLE* pDevice = (MIRA_DEVICE_HANDLE*) hDevice;
	static MIRA_SEARCH_RESULT resSearch = FREQ_SEARCH_FAIL;
	pDevice->ServiceSearchParam.eSearchStatus = MXD_POLLING_STATUS;
	pDevice->ServiceSearchParam.nStcNum = 0;
	pDevice->ServiceSearchParam.bStcStatus = FALSE;
	pDevice->ServiceSearchParam.nRefTick = 0;
	pDevice->nReSyncNum = 0;
	//pDevice->bAcsStatus = FALSE;  

	MXD_EX_WriteReg( pDevice, REG_STC_MISC_CTRL,0x0);//disable notch filter;
	DCC_ResetDevice( pDevice );

	MXD_DebugPrint( "OnStateBeginSearch::Begin to search ________%d_______ KHz!\n",pDevice->ServiceSearchParam.nCurrentFreqKhz );
	eRtnCode = DCC_TuneFrequency( pDevice,pDevice->ServiceSearchParam.nCurrentFreqKhz );
	if( MXD_RTN_OK != eRtnCode )
	{
		static MIRA_SEARCH_RESULT resSearch;
		MXD_DebugPrint( "OnStateBeginSearch::Tune Freq error!\n" );
		resSearch = FREQ_SEARCH_FAIL;
		STE_RequestChangeState( hDevice, MIRASTATE_SEARCHDONE, &resSearch );
	}
	else
	{
		if( MXD_RTN_OK != DCC_SyncSignal( pDevice ))
		{
			resSearch = FREQ_SEARCH_FAIL;
			STE_RequestChangeState( hDevice, MIRASTATE_SEARCHDONE, &resSearch );       
		}
		else
		{
			STE_RequestChangeState( hDevice, MIRASTATE_WAITLOCK, NULL );
		}
	}
	//ignore unexpected data interrupt.
	MXD_EX_WriteReg( hDevice, REG_HIC1_INT_CLEAR, 0xff );
}

void OnStateWaitLock( MXD_HANDLE hDevice, MIRA_SDK_STATE ePrevState, void* pParam )
{
	static MIRA_SEARCH_RESULT resSearch = FREQ_SEARCH_FAIL;
	MXD_RETURN_CODE eRtnCode = MXD_RTN_OK;
	MIRA_DEVICE_HANDLE* pDevice = (MIRA_DEVICE_HANDLE*) hDevice;

	eRtnCode = DCC_IsSignalLocked( pDevice );
	switch( eRtnCode )
	{
	case MXD_RTN_OK:
		pDevice->bSystemLockStatus = TRUE;
		STE_RequestChangeState( hDevice, MIRASTATE_GETCLCH, NULL );
		break;
	case MXD_POLLING_STATUS:
		//do nothing, remain current state.
		break;
	case MXD_CLCHCRC_FAIL:
		if( pDevice->nReSyncNum<2 )
		{
			MXD_DebugPrint("OnStateWaitLock::Crc fail,Resync...!\n");
			DCC_DetectCheMode( hDevice );
			DCC_ResetDevice( hDevice );
			if( MXD_RTN_OK != DCC_DetectFo( hDevice ))
			{
				resSearch = FREQ_SEARCH_FAIL;
				STE_RequestChangeState( hDevice, MIRASTATE_SEARCHDONE, &resSearch );                
			}
			else
			{
				MXD_WriteRegFields( hDevice, REG_CTRL, 7, 1, 1 );
				MXD_EX_WriteReg( hDevice, 0xcf, (MXD_UINT8)(pDevice->foVal));
				MXD_EX_WriteReg( hDevice, 0xd0, (MXD_UINT8)(pDevice->foVal>>8));
				MXD_EX_WriteReg( hDevice, 0xd1, (MXD_UINT8)(pDevice->foVal>>16));

				MXD_EX_WriteReg( hDevice, REG_INIT, 0x1 ); 
				MXD_DebugPrint("OnStateWaitLock::Cts init!\n");
				pDevice->ServiceSearchParam.nRefTick = 0;
				pDevice->nReSyncNum ++;
			}
		}
		else
		{
			resSearch = FREQ_SEARCH_FAIL;
			STE_RequestChangeState( hDevice, MIRASTATE_SEARCHDONE, &resSearch );			
		}
		break;
	case MXD_CTS_FAIL:
	case MXD_TIME_OUT:
	case MXD_FTS_FAIL_INT:
	case MXD_FTS_FAIL_CURRENT:
		resSearch = FREQ_SEARCH_FAIL;
		STE_RequestChangeState( hDevice, MIRASTATE_SEARCHDONE, &resSearch );
		break;

	default:
		break;	    
	}
	//ignore unexpected data interrupt.
	MXD_EX_WriteReg( hDevice, REG_HIC1_INT_CLEAR, 0xff );
}

void OnStateCheckStc( MXD_HANDLE hDevice, MIRA_SDK_STATE ePrevState, void* pParam )
{
	static MIRA_SEARCH_RESULT resSearch = FREQ_SEARCH_FAIL;
	MXD_RETURN_CODE eRtnCode = MXD_RTN_OK;
	MIRA_DEVICE_HANDLE* pDevice = (MIRA_DEVICE_HANDLE*) hDevice;

	DCC_DetectStc( hDevice );
	eRtnCode = DCC_IsStcExist( hDevice );
	if( MXD_RTN_OK == eRtnCode )
	{
		DCC_RemoveStc( pDevice );
		DCC_SyncSignal( pDevice );

		pDevice->ServiceSearchParam.nStcNum++;
		STE_RequestChangeState( hDevice, MIRASTATE_WAITLOCK, NULL );
	}
	else
	{
		resSearch = FREQ_SEARCH_FAIL;
		STE_RequestChangeState( hDevice, MIRASTATE_SEARCHDONE, &resSearch );
	}
	//ignore unexpected data interrupt.
	MXD_EX_WriteReg( hDevice, REG_HIC1_INT_CLEAR, 0xff );
}

void OnStateGetClch( MXD_HANDLE hDevice, MIRA_SDK_STATE ePrevState, void* pParam )
{
	static MIRA_SEARCH_RESULT resSearch = FREQ_SEARCH_FAIL;
	MIRA_DEVICE_HANDLE* pDevice = (MIRA_DEVICE_HANDLE*) hDevice;
	MXD_RETURN_CODE eRtnCode = MXD_RTN_OK;
	MXD_CMMBSERVICE_INFO *psvrInfos;
	MXD_UINT32 servicecount;

	//not work in TS interface
	if ( MXD_TS == pDevice->tDeviceConfig.eDataPath )
		return;

	eRtnCode = DTP_ClchProcess( hDevice, &psvrInfos, &servicecount );
	if ( MXD_RTN_OK == eRtnCode )
	{
		// when service name function actived, search work will not stop until the service name received from esg.
		if( pDevice->ServiceSearchParam.bGetServiceName )
		{
			STE_RequestChangeState( hDevice, MIRASTATE_STARTESG, NULL );
		}
		else
		{
			resSearch = FREQ_SEARCH_OK;
			pDevice->bSystemLockStatus = TRUE;
			STE_RequestChangeState( hDevice, MIRASTATE_SEARCHDONE, &resSearch );
		}
	}
	else if( MXD_POLLING_STATUS == eRtnCode )
		return; //continous waiting signal.
	else
	{
		resSearch = FREQ_SEARCH_FAIL;
		STE_RequestChangeState( hDevice, MIRASTATE_SEARCHDONE, &resSearch );
	}
}

void OnStateStartEsg( MXD_HANDLE hDevice, MIRA_SDK_STATE ePrevState, void* pParam )
{
	static MIRA_SEARCH_RESULT resSearch = FREQ_SEARCH_FAIL;
	MIRA_DEVICE_HANDLE* pDevice = (MIRA_DEVICE_HANDLE*) hDevice;
	//  MXD_RETURN_CODE eRtnCode = MXD_RTN_OK;

	if( MXD_RTN_OK == DTP_StartServiceNameReceive( hDevice ) )
	{
		pDevice->ServiceSearchParam.nRefTick = DCC_GetTickCount( hDevice );
		STE_RequestChangeState( hDevice, MIRASTATE_ESGRECEIVING, &resSearch );
	}
	else
	{
		//esg could not start? still return search result to user.
		resSearch = FREQ_SEARCH_OK;
		STE_RequestChangeState( hDevice, MIRASTATE_SEARCHDONE, &resSearch );
	}
	//ignore unexpected data interrupt.
	MXD_EX_WriteReg( hDevice, REG_HIC1_INT_CLEAR, 0xff );
}

void OnStateEsgReceiving( MXD_HANDLE hDevice, MIRA_SDK_STATE ePrevState, void* pParam )
{
	static MIRA_SEARCH_RESULT resSearch = FREQ_SEARCH_FAIL;
	MIRA_DEVICE_HANDLE* pDevice = (MIRA_DEVICE_HANDLE*) hDevice;
	MXD_RETURN_CODE eRtnCode = MXD_RTN_OK;
	MXD_UINT8    uIndex = 0;	

	if( DCC_GetTickCount( hDevice ) - pDevice->ServiceSearchParam.nRefTick > 3000 ) //time out?
	{
		resSearch = FREQ_SEARCH_OK;
		STE_RequestChangeState( hDevice, MIRASTATE_SEARCHDONE, &resSearch );
	}
	else
	{
		eRtnCode = DTP_CheckServiceData(pDevice, &uIndex);
		if (uIndex)
		{
			eRtnCode = DTP_ServiceDataProcess(pDevice, uIndex, TRUE);
			if( eRtnCode == MXD_RTN_OK )
			{
				resSearch = FREQ_SEARCH_OK;
				STE_RequestChangeState( hDevice, MIRASTATE_SEARCHDONE, &resSearch );
			}
		}
	}
}

void OnStateSearchDone( MXD_HANDLE hDevice, MIRA_SDK_STATE ePrevState, void* pParam )
{
	MIRA_DEVICE_HANDLE* pDevice = (MIRA_DEVICE_HANDLE*) hDevice;
	MIRA_SEARCH_RESULT* pRes = (MIRA_SEARCH_RESULT*)pParam;

	pDevice->ServiceSearchParam.nStcNum = 0;
	if( *pRes == FREQ_SEARCH_FAIL )
	{
		if( pDevice->m_fnCallbacks.OnServiceSearchResult )
			pDevice->m_fnCallbacks.OnServiceSearchResult( pDevice->nDemodChipIndex, pDevice->ServiceSearchParam.pSearchUserParam, pDevice->ServiceSearchParam.nCurrentFreqKhz, NULL, 0 );
	}
	else
	{
		MXD_DEMUXER_CONTEXT* pDemuxCtx = (MXD_DEMUXER_CONTEXT*)pDevice->pDemuxerPrivateStruct;
		if( pDevice->m_fnCallbacks.OnServiceSearchResult )
			pDevice->m_fnCallbacks.OnServiceSearchResult( pDevice->nDemodChipIndex, pDevice->ServiceSearchParam.pSearchUserParam, pDevice->ServiceSearchParam.nCurrentFreqKhz,  pDemuxCtx->m_pSeviceChannelList,  pDemuxCtx->m_nServiceCount  );
		if( pDevice->ServiceSearchParam.bGetServiceName )
			DTP_StopServiceNameReceive( hDevice );
	}

	if( pDevice->ServiceSearchParam.nCurrentFreqKhz >= pDevice->ServiceSearchParam.nEndFreqKhz )
	{
		STE_RequestChangeState( hDevice, MIRASTATE_IDLE, NULL );
	}
	else
	{
		pDevice->ServiceSearchParam.nCurrentFreqKhz += pDevice->ServiceSearchParam.nStepFreqKhz;
		STE_RequestChangeState( hDevice, MIRASTATE_BEGINSEARCH, NULL );
	}
	//ignore unexpected data interrupt.
	MXD_EX_WriteReg( hDevice, REG_HIC1_INT_CLEAR, 0xff );
}

void OnStateDataReceiving( MXD_HANDLE hDevice, MIRA_SDK_STATE ePrevState, void* pParam )
{
	MIRA_DEVICE_HANDLE* pDevice = (MIRA_DEVICE_HANDLE*) hDevice;
	MXD_RETURN_CODE eRtnCode = MXD_RTN_OK;
	MXD_UINT8    uIndex = 0, i;	

	DCC_ProcessGubao(hDevice);
	eRtnCode = DCC_GetSystemStatus( hDevice );
	if( MXD_SYSTEM_UNLOCK == eRtnCode )
	{
		pDevice->bSystemLockStatus = FALSE;
		STE_RequestChangeState( hDevice, MIRASTATE_STARTRECOVERY, NULL );
		for( i=0; i<6; i++ )
			pDevice->ActiveService[i].bCorrectDataGot = FALSE;
		//ingnore data, clean data interrupt.
		MXD_EX_WriteReg( hDevice, REG_HIC1_INT_CLEAR, 0xff );
	}
	else
	{
		if( MXD_BIG_DELAY == eRtnCode )
		{
			MXD_EX_WriteReg( hDevice, REG_CHE_CFG, 0x2 );
			MXD_DebugPrint( "OnStateDataReceiving:: Change to big delay mode!\n" );

		}
		if( 0 != pDevice->ServiceSearchParam.nRefTick )
		{
			if( ( MXD_NORMAL_DELAY == eRtnCode )&&((DCC_GetTickCount( hDevice ) - pDevice->ServiceSearchParam.nRefTick)>1000) )  
			{
				MXD_EX_WriteReg( hDevice, REG_CHE_CFG, 0x0 );
				MXD_DebugPrint( "OnStateDataReceiving:: Change to normal delay mode!\n" );
				pDevice->bBigDelayStatus = FALSE;
			}

			if( ( (MXD_POOR_SIGNAL == eRtnCode) )&&((DCC_GetTickCount( hDevice ) - pDevice->ServiceSearchParam.nRefTick)>LONG_TIME_RECOVERY_THLD))
			{
				if( 0 != LONG_TIME_RECOVERY_THLD )
				{
					pDevice->bSystemLockStatus = FALSE;
					MXD_DebugPrint( "OnStateDataReceiving:: Long time data error,begin to recovery!\n" );
					STE_RequestChangeState( hDevice, MIRASTATE_STARTRECOVERY, NULL );   
				}             
			}
		}
		else
		{
			pDevice->ServiceSearchParam.nRefTick = DCC_GetTickCount( hDevice );
		}

		if (MXD_TS != pDevice->tDeviceConfig.eDataPath)
		{
			eRtnCode = DTP_CheckServiceData(pDevice, &uIndex);
			if (uIndex)
			{
				eRtnCode = DTP_ServiceDataProcess(pDevice, uIndex, FALSE);
				//	#ifdef FIELDTEST_UPDATEREG
				//	FieldTestReadReg(pDevice, 1);
				//	#endif
			}
		}
		else
		{
			if( pDevice->m_fnCallbacks.OnReadTsData )
			{
				MXD_UINT32 nTsDataLen = 0;
				MXD_UINT8* pTsData = NULL;
				pDevice->m_fnCallbacks.OnReadTsData( pDevice->nDemodChipIndex, &pTsData, &nTsDataLen );
				if( nTsDataLen && pTsData )
				{
					MXD_TSPacketProcess( hDevice, pTsData, nTsDataLen );
				}
			}
		}
	}
}

void OnStateStartRecovery( MXD_HANDLE hDevice, MIRA_SDK_STATE ePrevState, void* pParam )
{
	//MXD_RETURN_CODE eRtnCode = MXD_RTN_OK;
	MIRA_DEVICE_HANDLE* pDevice = (MIRA_DEVICE_HANDLE*) hDevice;

	pDevice->ServiceSearchParam.nStcNum = 0;
	pDevice->ServiceSearchParam.eSearchStatus = MXD_POLLING_STATUS;
	pDevice->ServiceSearchParam.nStcNum = 0;
	pDevice->ServiceSearchParam.bStcStatus = FALSE;
	pDevice->ServiceSearchParam.nRefTick = 0;
	pDevice->nReSyncNum = 0;
	//pDevice->bAcsStatus = FALSE;  

	MXD_EX_WriteReg( pDevice, REG_STC_MISC_CTRL,0x0);//disable notch filter;
	DCC_TuneFrequency( pDevice,pDevice->ServiceSearchParam.nCurrentFreqKhz );
	if( MXD_RTN_OK != DCC_SyncSignal( pDevice ))
	{
		pDevice->bRecoveryStatus = TRUE;
		DCC_DetectCheMode( hDevice );
		STE_RequestChangeState( hDevice, MIRASTATE_STARTRECOVERY, NULL );       
	}
	else
	{   
		pDevice->bRecoveryStatus = TRUE;
		STE_RequestChangeState( hDevice, MIRASTATE_WAITRECOVERY, NULL ); 
	}
	//have not ready for get data, clean data interrupt.
	MXD_EX_WriteReg( hDevice, REG_HIC1_INT_CLEAR, 0xff );
}

void OnStateWaitRecovery( MXD_HANDLE hDevice, MIRA_SDK_STATE ePrevState, void* pParam )
{
	MXD_RETURN_CODE eRtnCode = MXD_RTN_OK;
	MIRA_DEVICE_HANDLE* pDevice = (MIRA_DEVICE_HANDLE*) hDevice;

	eRtnCode = DCC_IsSignalLocked( pDevice );
	switch( eRtnCode )
	{
	case MXD_RTN_OK:
		pDevice->bSystemLockStatus = TRUE;
		MXD_WriteRegFields( hDevice, REG_SFO_TRACK_CFG, 0x06, 2, 1); // 1s track mode
		// MXD_WriteRegFields( hDevice, REG_CTRL, 0x6,1, 0x0); // set ts slice mode
		MXD_WriteRegFields( hDevice, REG_CTRL, 0x6,1, 0x00);  //
		STE_RequestChangeState( hDevice, MIRASTATE_RECOVERYDONE, NULL );
		break;
	case MXD_POLLING_STATUS:
		//do nothing, remain current state.
		break;
	case MXD_CTS_FAIL:
	case MXD_CLCHCRC_FAIL:    
	case MXD_FTS_FAIL_INT:
	case MXD_FTS_FAIL_CURRENT:
	case MXD_TIME_OUT:
		DCC_DetectCheMode( hDevice );
		STE_RequestChangeState( hDevice, MIRASTATE_STARTRECOVERY, NULL );
		break;

	default:
		break;	    
	}
	//have not ready for get data, clean data interrupt.
	MXD_EX_WriteReg( hDevice, REG_HIC1_INT_CLEAR, 0xff );
}

void OnStateRecoveryDone( MXD_HANDLE hDevice, MIRA_SDK_STATE ePrevState, void* pParam )
{
	MXD_UINT8 regVal = 0;
	MIRA_DEVICE_HANDLE* pDevice = (MIRA_DEVICE_HANDLE*) hDevice;
	pDevice->bRecoveryStatus = FALSE;
	MXD_EX_ReadReg(pDevice, REG_SC_VALID_CFG, &regVal);
	if ((regVal & 0x1F)&&(pDevice->bCLCHEnable == FALSE))
	{
		MXD_WriteRegFields(pDevice, REG_SC_VALID_CFG,   5, 1, 0x0);
		MXD_WriteRegFields(pDevice, REG_OTDD_INT_CLEAR, 5, 1, 0x1);
		MXD_WriteRegFields(pDevice, REG_HIC1_INT_CLEAR, 5, 1, 0x1);
		MXD_WriteRegFields(pDevice, REG_SC5_CONFIG_B,   0, 5, 0x00);
		MXD_WriteRegFields(pDevice, REG_SC5_CONFIG_A,   0, 5, 0x00);
		pDevice->ActiveService[5].nActiveServiceID = 0x0;
	}
	STE_RequestChangeState( pDevice, MIRASTATE_DATARECEIVING, NULL );
	//have not ready for get data, clean data interrupt.
	MXD_EX_WriteReg( hDevice, REG_HIC1_INT_CLEAR, 0xff );
}

/*!
* Init for tuner, including demod for tuner and tuner itself
*
* \param hDevice    [ in ] Device handle
*
* \return Return code by MXD_RETURN_CODE enumeration
*
* \remarks 
*
*/
MXD_RETURN_CODE MXD_API DCC_InitTuner ( MXD_HANDLE hDevice )
{
	MXD_RETURN_CODE eRtnCode = MXD_RTN_OK;
	MXD_UINT8 regVal;
	MXD_UINT8 chipId=0;
	MXD_UINT32 tm=0;
	//MXD_UINT8 regVal1, regVal2, regVal3, regVal4;
	MIRA_DEVICE_HANDLE* pDevice = (MIRA_DEVICE_HANDLE*) hDevice;
	MXD_UINT8 i;
	MXD_UINT8 BBLutTable[] = {
		0xce,
		0xca,
		0xc6,
		0xc2,
		0xba,
		0xb6,
		0xb2,
		0xad,
		0xaa,
		0xa7,
		0xa3,
		0x9f,
		0x9b,
		0x98,
		0x94,
		0x92,
		0x90,
		0x8e,
		0x8c,
		0x8a,
		0x88,
		0x86,
		0x84,
		0x82,
		0x80,
		0x7e,
		0x7c,
		0x7a,
		0x78,
		0x76,
		0x74,
		0x72,
		0x70,
		0x6e,
		0x6c,
		0x6a,
		0x68,
		0x66,
		0x64,
		0x62,
		0x60,
		0x5e,
		0x5c,
		0x5a,
		0x58,
		0x56,
		0x54,
		0x52,
		0x50,
		0x4e,
		0x4c,
		0x4a,
		0x48,
		0x46,
		0x44,
		0x42,
		0x40,
		0x3e,
		0x3c,
		0x3a,
		0x38,
		0x36,
		0x34,
		0x32,
		0x30,
		0x2e,
		0x2a,
		0x28,
		0x25,
		0x22,
		0x1e,
		0x1b,
		0x18,
		0x15,
		0x12,
		0x0f,
		0x0c,
		0x08,
		0x04};

		/* Setup tuner interface */	
		MXD_EX_WriteReg( hDevice, REG_TIC_CONTROL, POLLUX_CTRL_REG_VAL );
		MXD_EX_WriteReg( hDevice, REG_SLAVE_ADD, POLLUX_SALVE_ADDR_VAL>>1 );
		MXD_EX_WriteReg( hDevice, REG_PRESCALE_COUNTER, POLLUX_I2CBRATE_CFIG_VAL );	   

		pDevice->nBBupBoundary = BB_UP_BOUNDARY;
		pDevice->nBBdownBoundary = BB_DOWN_BOUNDARY;

		for (i=0;i < sizeof(BBLutTable);i++)
		{/* download the lut table */
			MXD_EX_WriteReg( hDevice, REG_AGC_LUT_WRDATA_L, BBLutTable[sizeof(BBLutTable)-i-1]);  
			MXD_EX_WriteReg( hDevice, REG_AGC_LUT_WRADD, i );
		}

		MXD_EX_WriteReg( hDevice, REG_RF_MISC, RF_GAIN_DISABLE );

		MXD_EX_WriteReg( hDevice, REG_TUNER_BB_AGC_ADD, 0x44);//bb agc

		MXD_EX_WriteReg( hDevice, REG_AGC_INIT_DB, 0x2a);
		MXD_EX_WriteReg( hDevice, REG_AGC_MIN_DB, 0x0);
		MXD_EX_WriteReg( hDevice, REG_AGC_MAX_DB, 0x9a);
		MXD_EX_WriteReg( hDevice, REG_AGC_CFG, 0x04);
		MXD_EX_WriteReg( hDevice, REG_AGC_PARA_N, 0x01);


		MXD_WriteRegFields( hDevice, REG_CTRL, 0x5,1,1);//invert Q; 
#ifndef LPC_PIN_CTRL 
		MXD_EX_WriteReg( hDevice, REG_TUNER_LPC_ADD,0x02 ); 
		MXD_EX_WriteReg( hDevice, REG_TUNER_LPC_ACTIVE_DATA_H,0x0 );
		MXD_EX_WriteReg( hDevice, REG_TUNER_LPC_ACTIVE_DATA_L,0x0 );
		MXD_EX_WriteReg( hDevice, REG_TUNER_LPC_LP_DATA_H,0x06 );
		MXD_EX_WriteReg( hDevice, REG_TUNER_LPC_LP_DATA_L,0x06 );
		MXD_EX_WriteReg( hDevice, REG_TIC_LPC_CONTROL,0x08 ); //i2c control
#else

		MXD_EX_WriteReg( hDevice, REG_TIC_LPC_CONTROL,0x0a ); //pin control
#endif
		MXD_EX_WriteReg( hDevice, REG_AGC_BB_BACK_OFF_STEP, 0x09 );
		MXD_EX_WriteReg( hDevice, REG_AGC_BB_UP_BOUNDARY, pDevice->nBBupBoundary );
		MXD_EX_WriteReg( hDevice, REG_AGC_BB_DOWN_BOUNDARY, pDevice->nBBdownBoundary );


		MXD_EX_WriteReg( hDevice, REG_HOLD_AGC_CFG, 0x0 );//set holdagc to low: not hold

		MXD_EX_WriteReg( hDevice, REG_MISC_CFG, 0x6a); //RSSI enable,bbagc PGA enable,PDM polarity negetive    

		/* Check tuner read/write */
		tm = DCC_GetTickCount( hDevice );
		while( (DCC_GetTickCount(hDevice)-tm)<1000 )
		{
			MXD_EX_ReadTunerReg( hDevice, 0x1,&chipId );
			if(chipId == 0x05)
			{
				MXD_EX_WriteTunerReg( hDevice, 0xe, 0x55 );
				MXD_EX_ReadTunerReg( hDevice, 0xe, &regVal );

				if(0x55!=regVal)
				{
					MXD_DebugPrint("DCC_InitTuner:: write tuner register error,0xe=0x%x!\n",regVal);
					return MXD_GENERAL_ERROR;
				}
				MXD_DebugPrint("DCC_InitTuner:: check  tuner register r/w ok,cost time=%d!\n",DCC_GetTickCount(hDevice)-tm);
				break;
			}
		}
		if( chipId!=0x5 )
		{
			MXD_DebugPrint("DCC_InitTuner:: read tuner chip id  error,0x1=0x%x,cost time=%d!\n",chipId,DCC_GetTickCount(hDevice)-tm);
			return MXD_GENERAL_ERROR;	
		}
		/*Init tuner*/
		DCC_FlushReg(hDevice);
		return eRtnCode;
}/* enf of DCC_InitTuner( )*/

/*!
* Tune the tuner to the frequency, this function should be used 
* after DCC_InitTuner having been called.
*
* \param hDevice    [ in ] Device handle
* \param freqHz     [ in ] frequency to be tuned, unit: Hz
*
* \return Return code by MXD_RETURN_CODE enumeration
*
* \remarks 
*
*/
MXD_RETURN_CODE MXD_API DCC_SetTunerFreq (
	MXD_HANDLE hDevice,
	MXD_UINT32 freqHz )
{  
	//    MXD_RETURN_CODE rtnCode = MXD_RTN_OK;
	MXD_UINT32 Flo;
	MXD_UINT32 Fv11=  39;                                   
	MXD_UINT32 Fv12=  53;                                   
	MXD_UINT32 Fv13=  65;                                   
	MXD_UINT32 Fv21=  80;                                   
	MXD_UINT32 Fv22=  106;                                  
	MXD_UINT32 Fv23=  130;                                  
	MXD_UINT32 Fv31=  160;                                  
	MXD_UINT32 Fv32=  215;                                  
	MXD_UINT32 Fv33=  300;                                  
	MXD_UINT32 Fu1= 635;                                  
	MXD_UINT32 Fu2= 900;                                  
	MXD_UINT32 FL1= 1300;                                 
	MXD_UINT32 FL2= 1800;                                 
	MXD_UINT32 FS=  2700;                                 
	MXD_UINT32 Fref=  20;  // F_ref( MHz )                  
	MXD_UINT8 Scal= 18;  // Bit Num of Fractional-N of PLL  
	MXD_UINT8 reg_val;
	MXD_UINT8 reg_val_11,reg_val_12,reg_val_13;
	MXD_UINT32 VCO_SEL;
	MXD_UINT32 Fvco;
	MXD_UINT8 band_tp_8;
	MXD_UINT8 nDiv2,nDiv1,frac3,frac2,frac1;

	MXD_UINT32 quotientN,quatientFrac;

	MXD_UINT8 band_id = 0; 
	MXD_UINT32 band_type = 8000;
	MXD_UINT32 i,j;
	MXD_UINT32 freq_offset=0;

	Flo = (freqHz+freq_offset)/1000000;
	//Fref *=1000; 

	//=============initializing===========

	MXD_EX_WriteTunerReg(hDevice,0x02,0x3 ); //  

	/*Set lpf bandwidth*/
	switch(band_type)//LPF BW (kHz);
	{
	case 8000:
		band_type = 0;
		break;
	case 430:
		band_type = 1;
		break;
	case 2000:
		band_type = 2;
		break;
	case 1300:
		band_type = 3;
		break;
	case 5000:
		band_type = 5;
		break;
	case 6000:
		band_type = 6;
		break;
	case 7000:
		band_type = 7;
		break;

	default:
		break;
	}
	band_tp_8=band_type;
	MXD_EX_ReadTunerReg(hDevice,0x23,&reg_val);

	reg_val &= 0xf8;
	reg_val = reg_val|band_tp_8;
	MXD_EX_WriteTunerReg(hDevice,0x23, reg_val);


	/*band sel*/
	if( (Flo<= Fv11)&&(Flo*1000>28125))  /*VHF*/
	{   
		Fvco = 128*Flo;

		reg_val_12 = 0x02;
		reg_val_13 = 0x01;
	}
	else if( ( Flo<=Fv12 )&&( Flo>Fv11 ))          /////// VHF //////////
	{  
		Fvco = 96*Flo;

		reg_val_12 = 0x02; 
		reg_val_13 = 0x09;
	}
	else if( ( Flo<=Fv13 )&&( Flo>Fv12 ))          /////// UHF //////////
	{
		Fvco = 72*Flo;

		reg_val_12 = 0x04;
		reg_val_13 = 0x09;
	}
	else if( ( Flo<=Fv21 )&&( Flo>Fv13 ))           /////// UHF //////////
	{
		Fvco = 64*Flo;

		reg_val_12 = 0x02;  
		reg_val_13 = 0x02;  
	}
	else if( ( Flo<=Fv22 )&&( Flo>Fv21 ) )  /////// LBand ////////
	{
		Fvco = 48*Flo;

		reg_val_12 = 0x02;
		reg_val_13 = 0x0A;  
	}
	else if( ( Flo<=Fv23 )&&( Flo>Fv22 ))
	{
		Fvco = 36*Flo;

		reg_val_12 = 0x04;
		reg_val_13 = 0x0A;

	}
	else if (( Flo<=Fv31 )&&( Flo>Fv23 ))
	{
		Fvco = 32*Flo;

		reg_val_12 = 0x02;
		reg_val_13 = 0x04;    
	}
	else if( ( Flo<=Fv32 )&&( Flo>Fv31 ))
	{
		Fvco = 24*Flo;

		reg_val_12 = 0x02; 
		reg_val_13 = 0x0C;  
	}
	else if( ( Flo<=Fv33 )&&( Flo>Fv32 ))
	{
		Fvco = 18*Flo;

		reg_val_12 = 0x04; 
		reg_val_13 = 0x0C;  
	}
	else if( ( Flo<=Fu1 )&&( Flo>Fv33 ))
	{
		Fvco = 8*Flo;

		reg_val_12 = 0x12;
		reg_val_13 = 0x00;

	}
	else if(( Flo<=Fu2 )&&( Flo>Fu1 ))
	{
		Fvco = 6*Flo;

		reg_val_12 = 0x14;
		reg_val_13 = 0x00;   
	}
	else if( ( Flo<=FL1 )&&( Flo>Fu2 ))
	{
		Fvco = 4*Flo;

		reg_val_12 = 0x22;
		reg_val_13 = 0x00;
	}
	else if (( Flo<=FL2 )&&( Flo>FL1 ))
	{
		Fvco = 3*Flo;

		reg_val_12 = 0x24;
		reg_val_13 = 0x00;    
	}
	else if( ( Flo<=FS )&&( Flo>FL2 ))
	{
		Fvco = 2*Flo;

		reg_val_12 = 0x40;
		reg_val_13 = 0x00;   
	}    
	else
	{
		return MXD_GENERAL_ERROR;
	}

	MXD_EX_WriteTunerReg(hDevice,0x12,reg_val_12);  
	MXD_EX_WriteTunerReg(hDevice,0x13,reg_val_13); 

	//icp config
	VCO_SEL = 5427;
	if( ( Fvco<=3796 )&&( Fvco > 3631))
		VCO_SEL = 5042;
	else if(( Fvco<=3971 )&&( Fvco > 3796))
		VCO_SEL = 4643;
	else if( ( Fvco<=4293 )&&( Fvco > 3971))
		VCO_SEL = 4184;
	else if (( Fvco<=4528 )&&( Fvco > 4293))
		VCO_SEL = 3501;
	else if( ( Fvco<=4777 )&&( Fvco > 4528))
		VCO_SEL = 3318;
	else if( ( Fvco<=5164 )&&( Fvco > 4777))
		VCO_SEL = 2946;
	else if(( Fvco > 5164))
		VCO_SEL = 2516;
	reg_val = (VCO_SEL*774+1000)/(Fref*1000*20) + 45;
	//VCO 0x21 Setting
	MXD_EX_WriteTunerReg(hDevice,0x10,reg_val); 


	// Fractional-N PLL Settings    
	UTIL_DivToUint24( Fvco, Fref,&quotientN,&quatientFrac);
	if(quatientFrac==0)
	{
		MXD_EX_WriteTunerReg(hDevice,0x19,0x0); //bypass sdm
	}
	else
	{
		MXD_EX_WriteTunerReg(hDevice,0x19,0x0); //enable sdm
	}
	/* 24bits quatientFrac */
	quatientFrac += 1;
	quatientFrac = quatientFrac>>1;
	nDiv2 = (MXD_UINT8)(quotientN>>8);
	nDiv1 = (MXD_UINT8)quotientN;
	frac3 = (MXD_UINT8) ((quatientFrac>>16) & 0xff ); 
	frac2 = (MXD_UINT8) (quatientFrac >> 8)  & 0xff;    
	frac1 = (MXD_UINT8) (quatientFrac & 0xff);


	MXD_EX_WriteTunerReg(hDevice,0x14,nDiv2);
	MXD_EX_WriteTunerReg(hDevice,0x15,nDiv1);
	MXD_EX_WriteTunerReg(hDevice,0x16,frac3);
	MXD_EX_WriteTunerReg(hDevice,0x17,frac2);
	MXD_EX_WriteTunerReg(hDevice,0x18,frac1);

	MXD_EX_WriteTunerReg(hDevice, 0x00,0x00);//reset afc    

	MXD_EX_WriteTunerReg(hDevice,0x11,0x2e );
	MXD_EX_WriteTunerReg(hDevice,0x02,0x00);

	MXD_EX_WriteTunerReg(hDevice,0x11,0x2f );
	MXD_EX_WriteTunerReg(hDevice,0x1a,0x01 ); // afc setup
	MXD_EX_WriteTunerReg(hDevice,0x1b,0x02 ); // afc thr
	MXD_EX_WriteTunerReg(hDevice,0x1d,0x20 ); // afc_unlocknum
	MXD_EX_WriteTunerReg(hDevice,0x1e,0x02 ); // afc_locknum

	MXD_EX_WriteTunerReg(hDevice, 0x04,0x00);//system enters into sys-config mode



	MXD_EX_WriteTunerReg(hDevice, 0x00,0x06);//release afc

	MXD_EX_WriteTunerReg(hDevice, 0x03,0x20);//start AFC_FSM
	//MXD_EX_WriteTunerReg(hDevice, 0x02,0x00);//enter into op mode
	//DCC_Sleep(hDevice,25);     
	//MXD_EX_WriteTunerReg(hDevice, 0x00,0x37); //reset fd
	MXD_EX_WriteTunerReg(hDevice, 0x00,0x0e);//release fd

	for(i=0;i<50;i++)
	{
		for(j=0;j<7;j++)
		{
			MXD_EX_ReadTunerReg(hDevice, 0x6d, &reg_val );
		}
		if(0xc0!=(reg_val&0xc0))
		{
			if(0x80!=(reg_val&0x80)) //restart afc
			{
				MXD_EX_WriteTunerReg(hDevice, 0x00,0x08);//reset afc&fd
				MXD_EX_WriteTunerReg(hDevice, 0x11,0x2e);//reset afc )

				MXD_EX_WriteTunerReg(hDevice, 0x11,0x2f);//reset afc )
				MXD_EX_WriteTunerReg(hDevice, 0x00,0x0e);//reset afc&fd

				MXD_EX_WriteTunerReg(hDevice, 0x03,0x20);//start AFC_FSM, system       
				MXD_DebugPrint( "DCC_SetTunerFreq::Restart AFC_____Tuner 0x6d is: 0x%x!____________%d___________\n",reg_val,i );
			}  
			if(0x40!=(reg_val&0x40))//restart fd
			{
				MXD_EX_WriteTunerReg(hDevice, 0x0,0x06); //reset fd
				MXD_EX_WriteTunerReg(hDevice, 0x0,0x0e);//release fd          
				MXD_DebugPrint( "DCC_SetTunerFreq::Restart FD_____Tuner 0x6d is: 0x%x!____________%d____________\n",reg_val,i );
			}  
		}
		else
		{
			MXD_DebugPrint( "DCC_SetTunerFreq::_____Tuner 0x6d is: 0x%x!____________%d____________\n",reg_val,i );
			break;
		}
	}

	// SYN trigger
	// AGC related 
	//MXD_EX_WriteTunerReg(hDevice,0x0,0x1e);
	MXD_EX_WriteTunerReg(hDevice,0x0,0x0f);

	//MXD_EX_WriteTunerReg(hDevice,0x02,0x0);//go to sys_config 
	MXD_EX_WriteTunerReg(hDevice,0x03,0x1);//trigger agc_fsm

	return MXD_RTN_OK;
}/* end of DCC_SetTunerFreq( )*/

/*!
* Get tuner status. If locked, then return ok, if un-locked, then return failed.
*
* \param hDevice    [ in ] Device handle
*
* \return Return code by MXD_RETURN_CODE enumeration
*
* \remarks 
*
*/
MXD_RETURN_CODE MXD_API DCC_GetTunerStatus ( MXD_HANDLE hDevice )
{
	MXD_RETURN_CODE eRtnCode = MXD_GENERAL_ERROR;
	MXD_UINT8 regVal;
	MXD_UINT32 tick;

	tick = DCC_GetTickCount( hDevice );
	while( DCC_GetTickCount( hDevice ) - tick < 4000 )
	{
		MXD_EX_ReadTunerReg( hDevice, 0x6d, &regVal );
		if( 0xc3 == (regVal&0xc3) )
		{
			eRtnCode = MXD_RTN_OK;
			break;
		}

	}
	MXD_DebugPrint( "DCC_GetTunerStatus::________________Tuner 0x6d is: 0x%x!____________\n",regVal );
	return eRtnCode;
}/* end of DCC_GetTunerStatus( )*/

/*!
* AFC table calibration process
*
* \param hDevice    [ in ] Device handle
*
* \return Return code by MXD_RETURN_CODE enumeration
*
* \remarks 
*
*/
MXD_RETURN_CODE MXD_API DCC_ReadAfcTable ( MXD_HANDLE hDevice , MXD_UINT32* outFkUhf0, MXD_UINT32* outFkVhf0 )
{
	//  MXD_RETURN_CODE eRtnCode = MXD_GENERAL_ERROR;
	return MXD_RTN_OK;
}

/*!
* Init for tuner pga, including demod for tuner and tuner itself
*
* \param hDevice    [ in ] Device handle
*
* \return Return code by MXD_RETURN_CODE enumeration
*
* \remarks 
*
*/
MXD_RETURN_CODE MXD_API DCC_InitPga ( MXD_HANDLE hDevice )
{  
	return MXD_RTN_OK;    
}

MXD_RETURN_CODE DCC_UpdatePga( MXD_HANDLE hDevice )
{
	MIRA_DEVICE_HANDLE* pDevice = (MIRA_DEVICE_HANDLE*) hDevice;
	return MXD_RTN_OK;
}


/*!
* set data with certain bit.
*
* \param inDividend		[ in ]		dividend.
* \param inDivisor			[ in ]		divisor.
* \param outQuotientN		[ out ]		integer value of the quotient.
* \param outQuatientFrac	[ out ]		fractional value of the quotient. 
*
* \return Return code MXD_UINT8: 1: OK;0: the divisor is 0   
*
* \remark: (float)quatientN + (float)(quatientFrac)/(float)(1<<fracPosi)== (float)devidend/(float)divisor
*
*/
MXD_UINT8 UTIL_DivToUint24( MXD_UINT32 inDividend,
						   MXD_UINT32 inDivisor,
						   MXD_UINT32 * outQuotientN,
						   MXD_UINT32 * outQuatientFrac)
{

	MXD_UINT32 remainder;
	MXD_UINT32 quotientN;
	MXD_UINT32 quatientFrac;
	/*MXD_UINT8  fracPosi;*/
	MXD_UINT8 i;
	/*MXD_UINT8 j;*/
	MXD_UINT32 divisor  = inDivisor;
	MXD_UINT32 dividend = inDividend;       
	MXD_UINT8 scale=18;
	if (0 == divisor)
	{
		return 0;
	} 

	quotientN = dividend/divisor;

	remainder = dividend - quotientN*divisor;

	/* @here remainder < divisor */
	if (remainder>=0x80000000)
	{
		remainder = remainder >> 1;
		divisor   = divisor >> 1;
	}

	/* @here remainder <= divisor */
	quatientFrac = 0;

	if (remainder != divisor)
	{
		for (i=0;i<(scale+1);i++)
		{
			remainder = remainder<<1;    /* remainder *= 2; */

			if ( remainder >= divisor )
			{
				quatientFrac += 1;       /* BS_ (quatientFrac,bit0) */
				remainder -= divisor;
			}

			quatientFrac = quatientFrac<<1;
		} 

		if(0xffffff==quatientFrac )
		{
			quotientN++;
			quatientFrac = 0;
		}
		else
		{
			quatientFrac = (quatientFrac+1)>>1;
		}
	}

	else   /* remainder == divisor */
	{
		quotientN++;
		quatientFrac = 0;
	}

	*outQuotientN = quotientN;
	*outQuatientFrac = quatientFrac;

	return 1;
}


/*!
* flush tuner register to default
*
* \param hDevice    [ in ] Device handle
*
* \return Return code by MXD_RETURN_CODE enumeration
*
* \remarks 
*
*/
MXD_RETURN_CODE MXD_API DCC_FlushReg( MXD_HANDLE hDevice )
{
	MXD_RETURN_CODE eRtnCode = MXD_RTN_OK;
	MXD_UINT8 reg_table[] = {
		// basic function reset
		0x07, 0x0C, //  turn off LT
		0x08, 0x39, //  RFRSSI gain range config
		0x09, 0xc7,
		0x0A, 0x00, // set LNA current to max
		0x0B, 0x7D, // 7F->6D by Liu wenyong
		0x0C, 0xCC, // set FD ref to 20M
		0x0E, 0xBB,
		0x0F, 0xF0, // F5->F0 by Liu wenyong

		0x20, 0x66,
		0x21, 0x0f,  // LPF BW offset when ACS exist
		0x22, 0x01,  //01 auto FD Mode 00 host fd
		0x23, 0x30,
		0x24, 0x06, //offset to 3.8M
		0x38, 0x10,// set ACS threshold
		0x39, 0x21,// set ACS threshold
		0x3A, 0x00, // 01-00 
		0x3B, 0x02, // 05->02 by ymiao sar-adc average num

		0x3F, 0x01, // internal BB agc 

		0x45, 0x13,  //// Enable ACS mode

		0x4E, 0x3f,  //09->3f
		0x4F, 0x52,  // 99->92, mixer sample num //change to 0x0

		0x50, 0x55,
		0x51, 0x45,

		0x5E, 0x42,  //adcoc en by rbus

		0x62, 0x03,  // // disable far, acs, alt offset

		0xC8, 0x66,  //63->66 LNA 22dB 6dB step
		0xC9, 0x56,  //E3->56 LNA 16dB 6dB step
		0xCA, 0x46,  //53->46 LNA 10dB gain, 6dB step
		0xCB, 0x36,  //D3->36 LNA  4dB gain, 6dB step
		0xCC, 0x26,  //46->26 LNA -2dB gain, 6dB step
		0xCD, 0x10,  //36->10 LNA -8dB gain, 0dB step
		0xCE, 0x10,  //26->10 LNA -8dB gain, 0dB step
		//0xCF, 0x10,  //26->10 LNA -8dB gain, 0dB step
		//   ,     
		//
		// for far mode
		0xd0, 0x1f, // LNA_22dB, 0x06, VH, ok
		0xd1, 0x0d, // LNA_16dB, 0x05, VH, ok
		0xd2, 0x0b, // LNA_10dB, 0x04, VH, ok
		0xd3, 0x0b, // LNA_4dB,  0x03, VH, ok
		0xd4, 0x0b, // LNA_-2dB, 0x02, VH, ok
		0xd5, 0x0b, // LNA_-8dB, 0x01, VH  

		0xd8, 0x1d,  // LNA_22dB  0x06 VL ok, 0x20 
		0xd9, 0x18, // LNA_16dB  0x05 VL ok, 0x1d
		0xda, 0x16,  // LNA_10dB  0x04 VL ok, 0x1c
		0xdb, 0x18,  // LNA_4dB   0x03 VL ok, 0x1f
		0xdc, 0x17,  // LNA_-2dB  0x02 VL   , 0x17
		0xdd, 0x06,

		0xe0, 0x2f,  // LNA_22dB  0x06 VL ok, 0x20 
		0xe1, 0x2d, // LNA_16dB  0x05 VL ok, 0x1d
		0xe2, 0x2b,  // LNA_10dB  0x04 VL ok, 0x1c
		0xe3, 0x28,
		0xe4, 0x1c,
		0xe5, 0x19,
		0xe6, 0x18,
		0xe7, 0x17,
		0xe8, 0x0c,
		0xe9, 0x0b,
		0xea, 0x0a,
		0xeb, 0x09,
		0xec, 0x08,
		0xed, 0x07,
		0xee, 0x06,
		0xef, 0x05,
		0xf0, 0x04,
		0xf1, 0x03,
		0xf2, 0x02,
		0xf3, 0x01,
		0xf4, 0x00,
		0xff, 0xf4,
	};
	MXD_UINT32 i;
	for( i = 0; i< sizeof(reg_table); )
	{
		eRtnCode = MXD_EX_WriteTunerReg( hDevice, reg_table[i], reg_table[i+1] );
		if( MXD_RTN_OK != eRtnCode )
		{
			MXD_DebugPrint( "DCC_FlushReg:: Write tuner reg error! \n" );
			return eRtnCode;
		}
		i+=2;
	}
	return MXD_RTN_OK;
}

MXD_RETURN_CODE DCC_WriteAntennaDac( MXD_HANDLE hDevice, MXD_UINT32 nFreq  )
{

#ifdef USE_ANTENNA_DAC
	MIRA_DEVICE_HANDLE* pDevice = (MIRA_DEVICE_HANDLE*) hDevice;
	MXD_RETURN_CODE eRtnCode = MXD_GENERAL_ERROR;
	MXD_UINT8 ticStatus = 0;
	MXD_UINT8 i = 0, regValue=0, regAddr=0;
	MXD_UINT8 slavAddr = 0;

	MXD_EX_WriteTunerReg( hDevice, 0x02, 0x0 );
	MXD_EX_WriteTunerReg( hDevice, 0x09, 0xce);

	for( i=0; i<49; i++ )
	{
		if( g_AntennaTab[i].nFreq == nFreq )
			regValue = g_AntennaTab[i].nValue;
	}

	MXD_DebugPrint( "Writing Antenna Dac value = 0x%x\n", regValue );

	MXD_EX_WriteTunerReg( hDevice, 0x1f, regValue );

#endif
	return MXD_GENERAL_ERROR;    
}

MXD_RETURN_CODE DCC_ProcessGubao( MXD_HANDLE hDevice )
{
	MXD_INT8 pwr=0;
	MXD_INT8 entind=0;
	static lastpwr=0;
	static refTick=0;
	MXD_BOOL bFreqProcess = FALSE;

	pwr = DCC_GetSignalPwr( hDevice );
	if(lastpwr==0)
	{
		lastpwr = pwr;
		refTick = DCC_GetTickCount( hDevice);
	}
	if( (DCC_GetTickCount(hDevice)-refTick) >= 1000 )
	{
		if( (g_CurrentFreq == 754000000)||((g_CurrentFreq>=530000000)&&(g_CurrentFreq<=570000000)))
		{
			bFreqProcess = TRUE;
		}
		else
		{
			bFreqProcess = FALSE;
			MXD_EX_WriteTunerReg( hDevice, 0x09, 0xc7 );
			MXD_EX_WriteTunerReg( hDevice, 0xff, 0xf4 );
			MXD_EX_WriteTunerReg( hDevice, 0x24, 0x06 );
		}
		if ( bFreqProcess )
		{
			refTick = DCC_GetTickCount(hDevice);
			if( (pwr<-89))
			{
				if((bFreqProcess)&&(g_GubaoState!=3))
				{	
					MXD_EX_WriteTunerReg( hDevice, 0x24, 0xf );
					//MXD_EX_WriteTunerReg( hDevice, 0x22, 0x0 );
					MXD_EX_WriteTunerReg( hDevice, 0xff, 0xe0 );
					MXD_EX_WriteTunerReg( hDevice, 0xe0, 0x2f );
					MXD_EX_WriteTunerReg( hDevice, 0x09, 0xC3 );

					MXD_DebugPrint( "DCC_ProcessGubao:: Enter Gubao Process3! power=%d,Freq=%dHz\n",pwr,g_CurrentFreq );
					g_GubaoState = 3;

				}        
			}
			if( ((pwr<-82)&&(pwr>=-89)) )
			{
				if((g_GubaoState == 3)&&(pwr<-89+2))
				{
					goto END;
				}
				if((bFreqProcess)&&(g_GubaoState!=2))
				{
					MXD_EX_WriteTunerReg( hDevice, 0x24, 0xf );
					//MXD_EX_WriteTunerReg( hDevice, 0x22, 0x0 );
					MXD_EX_WriteTunerReg( hDevice, 0xff, 0xe0 );
					MXD_EX_WriteTunerReg( hDevice, 0xe0, 0x27 );
					MXD_EX_WriteTunerReg( hDevice, 0x09, 0xC3 );

					MXD_DebugPrint( "DCC_ProcessGubao:: Enter Gubao Process2! power=%d,Freq=%dHz\n",pwr,g_CurrentFreq );
					g_GubaoState = 2;

				}        
			}        
			/*if(((pwr <=- 77)&&( pwr >= -82 )))
			{
			if((g_GubaoState == 2)&&(pwr<-82+2))
			{
			goto END;
			}
			if((bFreqProcess)&&(g_GubaoState!=1))
			{
			MXD_EX_WriteTunerReg( hDevice, 0x24, 0xf );
			//MXD_EX_WriteTunerReg( hDevice, 0x22, 0x0 );
			MXD_EX_WriteTunerReg( hDevice, 0xff, 0xe0 );
			MXD_EX_WriteTunerReg( hDevice, 0xe0, 0x0c );
			MXD_EX_WriteTunerReg( hDevice, 0x09, 0xC3 );            
			MXD_DebugPrint( "DCC_ProcessGubao:: Enter Gubao Process1! power=%d,Freq=%dHz\n",pwr,g_CurrentFreq );
			g_GubaoState = 1;

			}
			}  */ 
			if( pwr>-80 )
			{
				if((bFreqProcess)&&(g_GubaoState>0))
				{
					MXD_EX_WriteTunerReg( hDevice, 0x24, 0xf );
					//MXD_EX_WriteTunerReg( hDevice, 0x22, 0x1 );
					MXD_EX_WriteTunerReg( hDevice, 0xe0, 0x2f );
					MXD_EX_WriteTunerReg( hDevice, 0x09, 0xc7 );
					MXD_EX_WriteTunerReg( hDevice, 0xff, 0xf4 );
					MXD_DebugPrint( "DCC_ProcessGubao:: Leave Gubao Process! \n" );
					g_GubaoState = 0;
					//lastpwr=pwr;
				}
			}
		}

	}
END:
	lastpwr=pwr;
	return MXD_RTN_OK;
}
